From a189aa23bbd2978efdf9ba422ddb3aa11c23a84a Mon Sep 17 00:00:00 2001 From: TDubovchenko Date: Fri, 17 May 2024 18:42:38 -0400 Subject: [PATCH 01/52] [EDITORIAL] v1.0 Correct typo in consumedunit.md (#459) Correct typo in column ID --- specification/columns/consumedunit.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/columns/consumedunit.md b/specification/columns/consumedunit.md index 0c9788cdc..0cdf2aa40 100644 --- a/specification/columns/consumedunit.md +++ b/specification/columns/consumedunit.md @@ -6,7 +6,7 @@ The ConsumedUnit column MUST be present in the billing data when the provider su ## Column ID -ConsumedeUnit +ConsumedUnit ## Display Name From 57d3b052dc1905143b9062eaeb436e4657bfbb06 Mon Sep 17 00:00:00 2001 From: AWS-ZachErdman <157180770+AWS-ZachErdman@users.noreply.github.com> Date: Fri, 17 May 2024 17:43:10 -0500 Subject: [PATCH 02/52] [EDITORIAL] Update columns.mdpp (#460) Fixed incorrect alphabetical order in Table of Contents. --- specification/columns/columns.mdpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/columns/columns.mdpp b/specification/columns/columns.mdpp index 423c7af43..f1d027b95 100644 --- a/specification/columns/columns.mdpp +++ b/specification/columns/columns.mdpp @@ -18,8 +18,8 @@ The FOCUS specification defines a group of columns that provide qualitative valu !INCLUDE "commitmentdiscountcategory.md",1 !INCLUDE "commitmentdiscountid.md",1 !INCLUDE "commitmentdiscountname.md",1 -!INCLUDE "commitmentdiscounttype.md",1 !INCLUDE "commitmentdiscountstatus.md",1 +!INCLUDE "commitmentdiscounttype.md",1 !INCLUDE "consumedquantity.md",1 !INCLUDE "consumedunit.md",1 !INCLUDE "contractedcost.md",1 From cc516f1cde9b240e577f0ce6f07e6b9f07250cb1 Mon Sep 17 00:00:00 2001 From: Joaquin Date: Fri, 17 May 2024 15:43:38 -0700 Subject: [PATCH 03/52] [EDITORIAL] Correct a typographical error in the ChargeCategory. (#461) Fix a typo. --- specification/columns/chargecategory.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/columns/chargecategory.md b/specification/columns/chargecategory.md index c0fa80162..aec82092e 100644 --- a/specification/columns/chargecategory.md +++ b/specification/columns/chargecategory.md @@ -31,7 +31,7 @@ Allowed values: | Value | Description | | :--------- | :------------------------------------| | Usage | Positive or negative charges based on the quantity of a service or resource that was consumed over a given period of time including refunds. | -| Purchase | Positive or negative charges for the acquisition of a service or resource bought upfront or on a recurring basis inluding refunds. | +| Purchase | Positive or negative charges for the acquisition of a service or resource bought upfront or on a recurring basis including refunds. | | Tax | Positive or negative applicable taxes that are levied by the relevant authorities including refunds. Tax charges may vary depending on factors such as the location, jurisdiction, and local or federal regulations. | | Credit | Positive or negative charges granted by the provider for various scenarios e.g promotional credits or corrections to promotional credits. | | Adjustment | Positive or negative charges the provider applies that do not fall into other category values. | From f7303b156794e9fb17199a86a78b691957412410 Mon Sep 17 00:00:00 2001 From: Joaquin Date: Fri, 17 May 2024 15:44:00 -0700 Subject: [PATCH 04/52] [PROCESS] update release planning content (#463) This PR outlines the planned release schedule and key milestones for the FOCUS project. It includes the scope and high-level system requirements for each version, as well as detailed timelines for the development and review processes of the upcoming releases. --- RELEASE-PLANNING.md | 105 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 102 insertions(+), 3 deletions(-) diff --git a/RELEASE-PLANNING.md b/RELEASE-PLANNING.md index 4352d40cc..cc66be493 100644 --- a/RELEASE-PLANNING.md +++ b/RELEASE-PLANNING.md @@ -1,8 +1,107 @@ ## Release Planning -This estimated time line was approved by the Members working group on the Feb 29 meeting. +This section outlines the planned release schedule and key milestones for the FOCUS project. It includes the scope and high-level system requirements for each version, as well as detailed timelines for the development and review processes for each present and past releases. - - +### FOCUS Releases Scope +
Estimated Timeline v1.0
+ + + + + + + + + + + + + + + + + + + + +
VersionRelease ByScope | High-Level System Requirements
v1.1Nov 11, 2024 + REQ 1: Keyword value/brief description
+ REQ 2: Keyword value/brief description
+ REQ 3: Keyword value/brief description +
v1.2Jun 20, 2025 + REQ 4: Keyword value/brief description
+ REQ 5: Keyword value/brief description
+ REQ 6: Keyword value/brief description +
v1.3Nov 11, 2025 + REQ 7: Keyword value/brief description
+ REQ 8: Keyword value/brief description
+ REQ 9: Keyword value/brief description +
+ +### Estimated Timeline for v1.1 +This table displays key milestones and dates related to the development of FOCUS Release v1.1. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DateMilestoneComment
16-May-24 to 19-Sep-24Start / End of the Development FOCUS Rel v1.117 weeks to develop FOCUS Rel v1.1
27-Jun-24Approval FOCUS v1.1 ScopeClose the scope for FOCUS Release v1.1
27-Jun-24 to 11-Jul-24Start / End Interim Consistency ReviewTwo weeks Interim Consistency Review FOCUS Rel v1.1
19-Sep-24 to 03-Oct-24Start / End of the FOCUS Rel v1.1 Final Consistency ReviewTwo weeks Final Consistency Review FOCUS Rel v1.1
03-Oct-24 to 08-Oct-24Preparing FOCUS Rel v1.1 baseline for IPR ReviewFive days to get ready the baseline Specifications for IPR Review
08-Oct-24 to 07-Nov-24Start / End of IPR Review v1.1During the 30-day period, members may exclude essential claims from their licensing commitments.
07-Nov-24WG Approve v1.1FOCUS Release Candidate v1.1. Approved by FOCUS Members
07-Nov-24SC Ratification v1.1FOCUS Steering Committee Ratifies v1.1
11-Nov-24FinOpsX Europe Announcement of v1.1Announcement of FOCUS Release v1.1 during the FinOpsX Europe Keynote (Barcelona)
+ + + + +### Estimated Timeline for v1.0 +FOCUS Release V1.1 will be announced during the FinOpsX event in San Diego on June 20, 2024. + From e30cbfd56b217b12121e87a1bda411d75ccff0ac Mon Sep 17 00:00:00 2001 From: Michael Flanakin Date: Fri, 24 May 2024 20:39:13 -0700 Subject: [PATCH 05/52] Fix changelog commit history link (#470) This PR fixes the commit history link in the changelog for 1.0. The previous link included more than just the 1.0 changes. --- CHANGELOG.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4aa3045de..1cd714bb5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + + ## v1.0 Announced June 20, 2024 @@ -96,7 +104,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), - `ChargeSubcategory` column - See `ChargeCategory` and `ChargeClass` columns -[All unreleased changes](https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/compare/v1.0-preview-cr...working_draft) +[All 1.0 changes](https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/compare/v1.0-preview-cr...1.0-cr)
From d21686f90ad7271945f25d47cc2f43e95812e499 Mon Sep 17 00:00:00 2001 From: Joaquin Date: Fri, 24 May 2024 20:39:47 -0700 Subject: [PATCH 06/52] [ADMIN] remove specific dates for 2025 releases (#468) --- RELEASE-PLANNING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RELEASE-PLANNING.md b/RELEASE-PLANNING.md index cc66be493..e2586f614 100644 --- a/RELEASE-PLANNING.md +++ b/RELEASE-PLANNING.md @@ -19,7 +19,7 @@ This section outlines the planned release schedule and key milestones for the FO
- + - + @@ -54,12 +54,12 @@ This table displays key milestones and dates related to the development of FOCUS - + - + From d8c7714e96dfc4bff4a0d83aa73dc202993a305b Mon Sep 17 00:00:00 2001 From: Joaquin Date: Thu, 13 Jun 2024 18:28:18 -0400 Subject: [PATCH 08/52] [ADMIN]update reference to patent policy 4 W3C mode as stated in the FOCUS Membership doc. (#480) It was identified that the reference to the Patent Policy was incorrect in the license document. It should be listed as Option 4, W3C mode, stated in the FOCUS Membership Agreement rather than Patent Policy Option 3: Open Web Foundation 1.0 Mode. See the screenshot below with the correct reference to the W3C Mode patent. ![image](https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/assets/3258579/25d47b58-7ae1-4a37-ad2a-443501ea1992) --- license.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/license.md b/license.md index fcfb59446..ac9a491f1 100644 --- a/license.md +++ b/license.md @@ -26,7 +26,7 @@ WHETHER BASED ON BREACH OF CONTRACT, TORT (INCLUDING NEGLIGENCE), OR OTHERWISE, AND WHETHER OR NOT THE OTHER MEMBER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -This document is governed by the Patent Policy Option 3: Open Web Foundation 1.0 Mode: +This document is governed by the Patent Policy Option 4: W3C Mode: See [project charter](https://github.com/FinOps-Open-Cost-and-Usage-Spec/foundation/blob/main/FOCUS_-_Membership_Agreement_Package_for_use.pdf).
From 4937e322cc60f6ed0757c875612bdaaf3eb2cdd4 Mon Sep 17 00:00:00 2001 From: AWS-ZachErdman <157180770+AWS-ZachErdman@users.noreply.github.com> Date: Thu, 13 Jun 2024 15:28:49 -0700 Subject: [PATCH 09/52] [EDITORIAL] Update billingperiodend.md (#483) I think we have the wrong word at the very beginning. This is supposed to be billing period end. --- specification/columns/billingperiodend.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/columns/billingperiodend.md b/specification/columns/billingperiodend.md index 61cf8981e..df698ce88 100644 --- a/specification/columns/billingperiodend.md +++ b/specification/columns/billingperiodend.md @@ -1,6 +1,6 @@ # Billing Period End -Billing Period Start represents the [*exclusive*](#glossary:exclusivebound) end date and time of a [*billing period*](#glossary:billing-period). For example, a time period where [BillingPeriodStart](#glossary:billingperiodstart) is '2024-01-01T00:00:00Z' and BillingPeriodEnd is '2024-02-01T00:00:00Z' includes charges for January, since BillingPeriodStart is [*inclusive*](#glossary:inclusivebound), but does not include charges for February since BillingPeriodEnd is *exclusive*. +Billing Period End represents the [*exclusive*](#glossary:exclusivebound) end date and time of a [*billing period*](#glossary:billing-period). For example, a time period where [BillingPeriodStart](#glossary:billingperiodstart) is '2024-01-01T00:00:00Z' and BillingPeriodEnd is '2024-02-01T00:00:00Z' includes charges for January, since BillingPeriodStart is [*inclusive*](#glossary:inclusivebound), but does not include charges for February since BillingPeriodEnd is *exclusive*. The BillingPeriodEnd column MUST be present in the billing data. This column MUST be of type [Date/Time Format](#date/timeformat), MUST be an *exclusive* value, and MUST NOT contain null values. The sum of the [BilledCost](#billedcost) column for [*rows*](#glossary:row) in a given *billing period* MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account). From f98495008de848c1b7af5efd370c6cb74e9afcad Mon Sep 17 00:00:00 2001 From: Graham Date: Wed, 10 Jul 2024 23:35:59 +1000 Subject: [PATCH 10/52] Update glossary - remove duplicate entry (#471) There is a duplicated entry in the glossary which needs to be removed. --------- Co-authored-by: Udam Dewaraja Co-authored-by: Joaquin --- specification/glossary.md | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/specification/glossary.md b/specification/glossary.md index 938cd28ec..7c11aeec0 100644 --- a/specification/glossary.md +++ b/specification/glossary.md @@ -52,6 +52,10 @@ Also known as Commitment Discount, this is a commitment for an amount of usage o A company or organization that provides remote access to computing resources, infrastructure, or applications for a fee. +Contracted Unit Price + +The agreed-upon unit price for a single [Pricing Unit](#pricingunit) of the associated SKU, inclusive of negotiated discounts, if present, and exclusive of any other discounts. This price is denominated in the [Billing Currency](#glossary:billingcurrency). + Dimension A specification-defined categorical attribute that provides context or categorization to billing data. @@ -84,14 +88,6 @@ A category of compute resources that can be paused or terminated by the CSP with The suggested provider-published unit price for a single [Pricing Unit](#pricingunit) of the associated [SKU](#glossary:sku), exclusive of any discounts. This price is denominated in the [Billing Currency](#glossary:billingcurrency). -Contracted Unit Price - -The agreed-upon unit price for a single [Pricing Unit](#pricingunit) of the associated SKU, inclusive of negotiated discounts, if present, and exclusive of any other discounts. This price is denominated in the [Billing Currency](#glossary:billingcurrency). - -Contracted Unit Price - -The agreed-upon unit price for a single [Pricing Unit](#pricingunit) of the associated SKU, inclusive of negotiated discounts, if present, and exclusive of any other discounts. This price is denominated in the [Billing Currency](#glossary:billingcurrency). - Metric A FOCUS-defined column that provides numeric values, allowing for aggregation operations such as arithmetic operations (sum, multiplication, averaging etc.) and statistical operations. From 7557df7e6d19e73798ad95d01a3fe7254f152c4a Mon Sep 17 00:00:00 2001 From: Michael Flanakin Date: Mon, 15 Jul 2024 11:19:08 -0700 Subject: [PATCH 11/52] Rename CommitmentDiscountStatus supporting content file (#481) This just cleans up outdated supporting content --------- Co-authored-by: chandra-cloudtrakr <111657294+chandra-cloudtrakr@users.noreply.github.com> Co-authored-by: Joaquin --- .../{commitmentdiscountusage.md => commitmentdiscountstatus.md} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename supporting_content/columns/{commitmentdiscountusage.md => commitmentdiscountstatus.md} (96%) diff --git a/supporting_content/columns/commitmentdiscountusage.md b/supporting_content/columns/commitmentdiscountstatus.md similarity index 96% rename from supporting_content/columns/commitmentdiscountusage.md rename to supporting_content/columns/commitmentdiscountstatus.md index b8306232f..dfd849aac 100644 --- a/supporting_content/columns/commitmentdiscountusage.md +++ b/supporting_content/columns/commitmentdiscountstatus.md @@ -1,4 +1,4 @@ -# Column: CommitmentDiscountUsage +# Column: CommitmentDiscountStatus ## Example provider mappings From 3330cc405a731c9cd0f1f2e90e015763e67ee725 Mon Sep 17 00:00:00 2001 From: Joaquin Date: Mon, 15 Jul 2024 20:20:17 +0200 Subject: [PATCH 12/52] [REPO] Enhance Issue Templates (#490) ### Enhance Template: `issue feedback ` This addition explicitly requests users to provide relevant data or data extracts along with their feedback. It emphasizes the importance of data in supporting discussions and decision-making while reminding submitters to ensure that the data is anonymized and compliant with privacy guidelines. ### Enhance Template: `discussion Topic` This YAML replaces the previous `discussion-topic.md` file. It defines the structure and content of the GitHub issue form for discussing broad topics within the FOCUS community. It ensures that all necessary information is gathered effectively, including an optional field for attaching relevant data, which will support the discussion with tangible examples. ### Enhance Template: `maintenance` This YAML template is structured to gather essential information about maintenance tasks within the GitHub repository or actions. The format ensures clarity and specificity in the task descriptions and outcomes, facilitating effective task management and completion. ### Enhance Template: `spec-change` This template provides a YAML format for submitting specification changes, ensuring that all relevant information is captured, including the type of issue, whether the issue is normalized, a detailed description, a clear definition of what constitutes completion of the task, and an optional section for additional context or supporting information. This approach ensures clarity and facilitates the efficient management of specification changes. --- .github/ISSUE_TEMPLATE/discussion-topic.yml | 45 ++++++++++++++++++ .github/ISSUE_TEMPLATE/feedback.yml | 10 +++- .github/ISSUE_TEMPLATE/maintenance.yml | 21 +++++++++ .github/ISSUE_TEMPLATE/spec-change.md | 1 - .github/ISSUE_TEMPLATE/spec_change.yml | 51 +++++++++++++++++++++ 5 files changed, 126 insertions(+), 2 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/discussion-topic.yml create mode 100644 .github/ISSUE_TEMPLATE/maintenance.yml create mode 100644 .github/ISSUE_TEMPLATE/spec_change.yml diff --git a/.github/ISSUE_TEMPLATE/discussion-topic.yml b/.github/ISSUE_TEMPLATE/discussion-topic.yml new file mode 100644 index 000000000..04310627b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/discussion-topic.yml @@ -0,0 +1,45 @@ +name: Discussion Topic +description: Initiate discussion on broad topics within the FOCUS community. +title: "[DISCUSSION]: " +labels: ["discussion topic"] +assignees: ["mike-finopsorg,udam-f2"] +body: + - type: textarea + attributes: + label: Description + description: Describe the discussion topic, the discussions that have already taken place, and where community feedback is needed. Provide specifics, especially if there are multiple possible options. + placeholder: Describe the topic and any prior discussions here. + validations: + required: true + + - type: textarea + attributes: + label: Proposed Approach + description: Describe the approach that your group is proposing for the discussion topic. + placeholder: Outline your proposed approach here. + validations: + required: true + + - type: input + attributes: + label: GitHub Issue or Reference + description: If the topic is related to a particular work item, reference the GitHub issue here. If it's a specification-wide topic, indicate that. + placeholder: e.g., Issue #123 or Specification-wide + validations: + required: false + + - type: textarea + attributes: + label: Context + description: Add any context that may help the community think through this and provide useful feedback. + placeholder: Provide additional context here. + validations: + required: false + + - type: textarea + attributes: + label: Data Submission for Discussion + description: Provide relevant sample data or data extracts that support your discussion. Ensure data is anonymized and does not include sensitive or proprietary information. + placeholder: Attach sample data or data extracts here. Ensure compliance with data privacy guidelines. + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/feedback.yml b/.github/ISSUE_TEMPLATE/feedback.yml index 8ec5572b6..1ab51c5c0 100644 --- a/.github/ISSUE_TEMPLATE/feedback.yml +++ b/.github/ISSUE_TEMPLATE/feedback.yml @@ -1,7 +1,7 @@ name: FinOps Use Case Feedback description: Provide feedback on FinOps use cases that cannot be performed with the current FOCUS specification. title: "[FEEDBACK]: " -labels: ["feedback", "use-case"] +labels: [""] assignees: ["mike-finopsorg,udam-f2"] body: - type: markdown @@ -59,3 +59,11 @@ body: validations: required: true + - type: textarea + attributes: + label: Data Submission for Discussion + description: Provide relevant sample data or data extracts that support your feedback. Ensure data is anonymized and does not include sensitive or proprietary information. + placeholder: Attach sample data or data extracts here. Ensure compliance with data privacy guidelines. + validations: + required: false + diff --git a/.github/ISSUE_TEMPLATE/maintenance.yml b/.github/ISSUE_TEMPLATE/maintenance.yml new file mode 100644 index 000000000..3a39989ce --- /dev/null +++ b/.github/ISSUE_TEMPLATE/maintenance.yml @@ -0,0 +1,21 @@ +name: Maintenance Task +description: Create tasks related to work on the GitHub Repository or GitHub Actions. +title: "[MAINTENANCE]: " +labels: ["repo maintenance"] +assignees: ["mike-finopsorg,udam-f2"] +body: + - type: textarea + attributes: + label: Description + description: Describe the maintenance issue that needs to be addressed. + placeholder: Provide a detailed description of the maintenance task here. + validations: + required: true + + - type: textarea + attributes: + label: Definition of Done + description: Describe the outcomes that will indicate the task has been successfully completed. + placeholder: Specify what 'done' looks like for this task. + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/spec-change.md b/.github/ISSUE_TEMPLATE/spec-change.md index 9d1b5f284..0e8003855 100644 --- a/.github/ISSUE_TEMPLATE/spec-change.md +++ b/.github/ISSUE_TEMPLATE/spec-change.md @@ -4,7 +4,6 @@ about: Spec change issue title: Spec Change title labels: spec change assignees: '' - --- ### Type diff --git a/.github/ISSUE_TEMPLATE/spec_change.yml b/.github/ISSUE_TEMPLATE/spec_change.yml new file mode 100644 index 000000000..344bdcc8c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/spec_change.yml @@ -0,0 +1,51 @@ +name: Spec Change +description: Submit changes or updates to the current specification. +title: "[SPEC CHANGE]: " +labels: ["discussion topic"] +assignees: ["mike-finopsorg,udam-f2"] +body: + - type: dropdown + attributes: + label: Type of Issue + description: Select the type of spec change (e.g., Dimension, Metric, Attribute, Documentation). + options: + - 'Dimension' + - 'Metric' + - 'Attribute' + - 'Documentation' + validations: + required: true + + - type: checkboxes + attributes: + label: Normalized + description: Indicate if the dimension is normalized. + options: + - label: "Yes" + - label: "No" + validations: + required: true + + - type: textarea + attributes: + label: Description + description: Describe the issue and the changes being proposed. + placeholder: Provide a detailed description of the spec change. + validations: + required: true + + - type: textarea + attributes: + label: Definition of Done + description: Checklist of items that define the completion of the spec change. + placeholder: "- Rationalize vendor-neutral, cross-cloud naming\n- Complete spec template and include naming, constraints, guidelines\n- Include principles and governance criteria for maintaining normalized dimensions" + validations: + required: true + + - type: textarea + attributes: + label: Context / Supporting Information + description: Provide any additional context that may help in understanding or evaluating the spec change. Include mappings between normalized values and vendor-specified values if applicable. + placeholder: Additional context, references to other issues, or any relevant supporting information. + validations: + required: false From 369ae31015f35d0ed9919f067e1d13044403185b Mon Sep 17 00:00:00 2001 From: Karl <133434112+kk09v@users.noreply.github.com> Date: Thu, 18 Jul 2024 14:36:36 -0500 Subject: [PATCH 13/52] [EDITORIAL] Reclassify ConsumedUnit as Dimension instead of Metric (#506) Correct ConsumedUnit column type to Dimension from Metric (similar to PricingUnit) because it is an attribute of how the consumption is measured and is not able to have mathematical operations applied to it. --- specification/columns/consumedunit.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/columns/consumedunit.md b/specification/columns/consumedunit.md index 0cdf2aa40..f0f71870a 100644 --- a/specification/columns/consumedunit.md +++ b/specification/columns/consumedunit.md @@ -20,7 +20,7 @@ Provider-specified measurement unit indicating how a provider measures usage of | Constraint | Value | |:----------------|:----------------| -| Column type | Metric | +| Column type | Dimension | | Feature level | Conditional | | Allows nulls | True | | Data type | String | From b5c125c9f7ec6b6c1c1569af22ab42611e55e82a Mon Sep 17 00:00:00 2001 From: Joaquin Date: Mon, 22 Jul 2024 21:37:25 +0200 Subject: [PATCH 14/52] Proposal for FOCUS v1.1 Scope (#504) **Irena** and **Udam** have been working offline to formalize the scope for FOCUS v1.1. This proposal is based on the current discussions and Issues discussed in the three Task Forces (TF-1, TF-2, and TF-3). In a nutshell, here is what Udam and I are proposing: > _**SKU and SKU Price Details**_ > _Provide deeper visibility into SKU and SKU Price details (in addition to the current SKU and SKU Price IDs that are available in FOCUS) which enables many standard FinOps use cases from cost reporting to commitment optimization._ > >_**Deeper service classification**_ >_Move beyond the highest-level service categorization to a sub-categorization for services while adding flexibility for providers to share their native categorizations within FOCUS._ > >_**Capacity Reservation**_ >_Ability to represent on-demand capacity reservations within FOCUS datasets_ > >_**Improved metadata support**_ >_Strengthen the correlation between FOCUS-compatible datasets and the corresponding metadata to better support data analysis and ETL use cases._ If everyone agrees, we could add that to the Release Planning as a high-level scope for FOCUS 1.1. --- RELEASE-PLANNING.md | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/RELEASE-PLANNING.md b/RELEASE-PLANNING.md index f1b5a655d..34b21361f 100644 --- a/RELEASE-PLANNING.md +++ b/RELEASE-PLANNING.md @@ -12,9 +12,26 @@ This section outlines the planned release schedule and key milestones for the FO
@@ -61,7 +78,7 @@ This table displays key milestones and dates related to the development of FOCUS - + From e0f2f166a894d0bcbe7cec973ee8d95945d1a0c8 Mon Sep 17 00:00:00 2001 From: Andrew Qu <115758900+aqu-erp@users.noreply.github.com> Date: Fri, 2 Aug 2024 11:05:38 -0700 Subject: [PATCH 15/52] FOCUS dataset consistency review (#474) Resolving #472 ### Acceptance - [ ] select a term to used to describe a FOCUS compliant dataset - [ ] defining term in glossary - [ ] maintain consistent usage of term across specification and changelog, etc. - [ ] add glossary anchors where needed - [ ] confirm convention for referring to a generic potentially noncompliant dataset from a provider ### Proposed term and definition `FOCUS Dataset` `A structured collection of cost and usage data that meets or exceeds the Basic compliance criteria of FOCUS.` --- ### Open Questions When to retain use of `billing data` - When used in general context of FinOps data at large #### Examples Overview.md >FOCUS aims to establish a community-driven specification for consumption-based _billing data_. >_Billing data_ generators: Infrastructure and services providers that bill based on consumption Readme.md >The FOCUS spec will make it easier to merge multiple _billing data_ sources together --- ### Notes - Term replaces instances of `-`, `billing data`, and `cost data` in normative statements - Term does not refer to dataset supplied/created/provided by the spec - Term refers to dataset that is being described by normative statements - a dataset that meets certain compliance criteria --------- Co-authored-by: Irena Jurica --- CHANGELOG.md | 2 +- specification/attributes/attributes.mdpp | 2 +- specification/attributes/column_naming_and_ordering.md | 2 +- specification/attributes/currency_code_format.md | 2 +- specification/attributes/datetime_format.md | 2 +- specification/attributes/discount_handling.md | 2 +- specification/attributes/key_value_format.md | 2 +- specification/attributes/numeric_format.md | 2 +- specification/attributes/string_handling.md | 2 +- specification/attributes/unit_format.md | 4 ++-- specification/columns/availabilityzone.md | 2 +- specification/columns/billedcost.md | 2 +- specification/columns/billingaccountid.md | 2 +- specification/columns/billingaccountname.md | 2 +- specification/columns/billingcurrency.md | 2 +- specification/columns/billingperiodend.md | 2 +- specification/columns/billingperiodstart.md | 2 +- specification/columns/chargecategory.md | 2 +- specification/columns/chargeclass.md | 2 +- specification/columns/chargedescription.md | 2 +- specification/columns/chargefrequency.md | 2 +- specification/columns/chargeperiodend.md | 2 +- specification/columns/chargeperiodstart.md | 2 +- specification/columns/commitmentdiscountcategory.md | 2 +- specification/columns/commitmentdiscountid.md | 2 +- specification/columns/commitmentdiscountname.md | 2 +- specification/columns/commitmentdiscountstatus.md | 2 +- specification/columns/commitmentdiscounttype.md | 2 +- specification/columns/consumedquantity.md | 2 +- specification/columns/consumedunit.md | 2 +- specification/columns/contractedcost.md | 2 +- specification/columns/contractedunitprice.md | 2 +- specification/columns/effectivecost.md | 2 +- specification/columns/invoiceissuer.md | 2 +- specification/columns/listcost.md | 2 +- specification/columns/listunitprice.md | 2 +- specification/columns/pricingcategory.md | 2 +- specification/columns/pricingquantity.md | 2 +- specification/columns/pricingunit.md | 2 +- specification/columns/provider.md | 2 +- specification/columns/publisher.md | 2 +- specification/columns/regionid.md | 2 +- specification/columns/regionname.md | 2 +- specification/columns/resourceid.md | 2 +- specification/columns/resourcename.md | 2 +- specification/columns/resourcetype.md | 2 +- specification/columns/servicecategory.md | 2 +- specification/columns/servicename.md | 2 +- specification/columns/skuid.md | 2 +- specification/columns/skupriceid.md | 2 +- specification/columns/subaccountid.md | 2 +- specification/columns/subaccountname.md | 2 +- specification/columns/tags.md | 6 +++--- specification/glossary.md | 4 ++++ 54 files changed, 60 insertions(+), 56 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1cd714bb5..96131dca2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -187,7 +187,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ## Columns History -This table maps the evolution of the billing data, showcasing column introductions and updates from its initial version 0.5 to the comprehensive revisions in "1.0-preview", "1.0" and beyond. +This table maps the evolution of the specification, showcasing column introductions and updates from its initial version 0.5 to the comprehensive revisions in "1.0-preview", "1.0" and beyond. | **Column ID** | **Revision Introduced** | **Status** | |------------------------------|-------------------------|-------------------| diff --git a/specification/attributes/attributes.mdpp b/specification/attributes/attributes.mdpp index 240feac6a..36fe447e9 100644 --- a/specification/attributes/attributes.mdpp +++ b/specification/attributes/attributes.mdpp @@ -1,6 +1,6 @@ # Attributes -Attributes are requirements that apply across a billing dataset instead of an individual column level. Requirements on data content can include naming +Attributes are requirements that apply across a FOCUS dataset instead of an individual column level. Requirements on data content can include naming conventions, data types, formatting standardizations, etc. Attributes may introduce high-level requirements for data granularity, recency, frequency, etc. Requirements defined in attributes are necessary for servicing [FinOps capabilities][FODOFC] accurately using a standard set of instructions regardless of the origin of the data. diff --git a/specification/attributes/column_naming_and_ordering.md b/specification/attributes/column_naming_and_ordering.md index 1ae74bac0..1b279efb1 100644 --- a/specification/attributes/column_naming_and_ordering.md +++ b/specification/attributes/column_naming_and_ordering.md @@ -14,7 +14,7 @@ Column Naming and Ordering ## Description -Naming and ordering convention for columns appearing in billing data. +Naming and ordering convention for columns appearing in a FOCUS dataset. ## Requirements diff --git a/specification/attributes/currency_code_format.md b/specification/attributes/currency_code_format.md index b9811ca3b..68c5b2a68 100644 --- a/specification/attributes/currency_code_format.md +++ b/specification/attributes/currency_code_format.md @@ -14,7 +14,7 @@ Currency Code Format ## Description -Formatting for currency columns appearing in billing data. +Formatting for currency columns appearing in a FOCUS dataset. ## Requirements diff --git a/specification/attributes/datetime_format.md b/specification/attributes/datetime_format.md index 895ec64bd..d04b6e032 100644 --- a/specification/attributes/datetime_format.md +++ b/specification/attributes/datetime_format.md @@ -14,7 +14,7 @@ Date/Time Format ## Description -Rules and formatting requirements for date/time-related columns appearing in billing data. +Rules and formatting requirements for date/time-related columns appearing in a FOCUS dataset. ## Requirements diff --git a/specification/attributes/discount_handling.md b/specification/attributes/discount_handling.md index b641646ed..aa48d8f1b 100644 --- a/specification/attributes/discount_handling.md +++ b/specification/attributes/discount_handling.md @@ -20,7 +20,7 @@ Discount Handling ## Description -Indicates how to include and apply discounts to usage charges or rows. +Indicates how to include and apply discounts to usage charges or rows in a FOCUS dataset. ## Requirements diff --git a/specification/attributes/key_value_format.md b/specification/attributes/key_value_format.md index 06f592efd..136d81447 100644 --- a/specification/attributes/key_value_format.md +++ b/specification/attributes/key_value_format.md @@ -14,7 +14,7 @@ Key-Value Format ## Description -Rules and formatting requirements for columns appearing in billing data that convey data as key-value pairs. +Rules and formatting requirements for columns appearing in a FOCUS dataset that convey data as key-value pairs. ## Requirements diff --git a/specification/attributes/numeric_format.md b/specification/attributes/numeric_format.md index a187f3233..992a60c56 100644 --- a/specification/attributes/numeric_format.md +++ b/specification/attributes/numeric_format.md @@ -14,7 +14,7 @@ Numeric Format ## Description -Rules and formatting requirements for numeric columns appearing in billing data. +Rules and formatting requirements for numeric columns appearing in a FOCUS dataset. ## Requirements diff --git a/specification/attributes/string_handling.md b/specification/attributes/string_handling.md index 9e554777c..108fb8f08 100644 --- a/specification/attributes/string_handling.md +++ b/specification/attributes/string_handling.md @@ -14,7 +14,7 @@ String Handling ## Description -Requirements for string-capturing columns appearing in billing data. +Requirements for string-capturing columns appearing in a FOCUS dataset. ## Requirements diff --git a/specification/attributes/unit_format.md b/specification/attributes/unit_format.md index c428b8429..7fa10a32c 100644 --- a/specification/attributes/unit_format.md +++ b/specification/attributes/unit_format.md @@ -1,6 +1,6 @@ # Unit Format -Billing data frequently captures data measured in units related to data size, count, time, and other [*dimensions*](#glossary:dimension). The Unit Format attribute provides a standard for expressing units of measure in columns appearing in billing data. +Billing data frequently captures data measured in units related to data size, count, time, and other [*dimensions*](#glossary:dimension). The Unit Format attribute provides a standard for expressing units of measure in columns appearing in a FOCUS dataset. All columns defined in FOCUS specifying Unit Format as a value format MUST follow the requirements listed below. @@ -14,7 +14,7 @@ Unit Format ## Description -Indicates standards for expressing measurement units in columns appearing in billing data. +Indicates standards for expressing measurement units in columns appearing in a FOCUS dataset. ## Requirements diff --git a/specification/columns/availabilityzone.md b/specification/columns/availabilityzone.md index e8dfb3681..ea1fbcca2 100644 --- a/specification/columns/availabilityzone.md +++ b/specification/columns/availabilityzone.md @@ -2,7 +2,7 @@ An [*availability zone*](#glossary:availability-zone) is a provider-assigned identifier for a physically separated and isolated area within a Region that provides high availability and fault tolerance. Availability Zone is commonly used for scenarios like analyzing cross-zone data transfer usage and the corresponding cost based on where [*resources*](#glossary:resource) are deployed. -The AvailabilityZone column is RECOMMENDED to be present in the billing data when the provider supports deploying resources or services within an *availability zone*. This column MUST be of type String and MAY contain null values when a charge is not specific to an *availability zone*. +The AvailabilityZone column is RECOMMENDED to be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports deploying resources or services within an *availability zone*. This column MUST be of type String and MAY contain null values when a charge is not specific to an *availability zone*. ## Column ID diff --git a/specification/columns/billedcost.md b/specification/columns/billedcost.md index 942984eb2..da70e1d38 100644 --- a/specification/columns/billedcost.md +++ b/specification/columns/billedcost.md @@ -2,7 +2,7 @@ The [*billed cost*](#glossary:billed-cost) represents a charge serving as the basis for invoicing, inclusive of the impacts of all reduced rates and discounts while excluding the [*amortization*](#glossary:amortization) of relevant purchases (one-time or recurring) paid to cover future eligible charges. This cost is denominated in the [Billing Currency](#billingcurrency). The Billed Cost is commonly used to perform FinOps capabilities that require cash-basis accounting such as cost allocation, budgeting, and invoice reconciliation. -The BilledCost column MUST be present in the billing data and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat), and be denominated in the BillingCurrency. The sum of the BilledCost for [*rows*](#glossary:row) in a given [*billing period*](#glossary:billing-period) MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account). +The BilledCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat), and be denominated in the BillingCurrency. The sum of the BilledCost for [*rows*](#glossary:row) in a given [*billing period*](#glossary:billing-period) MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account). ## Column ID diff --git a/specification/columns/billingaccountid.md b/specification/columns/billingaccountid.md index cf511607c..e2b3a1a74 100644 --- a/specification/columns/billingaccountid.md +++ b/specification/columns/billingaccountid.md @@ -2,7 +2,7 @@ A Billing Account ID is a provider-assigned identifier for a [*billing account*](#glossary:billing-account). *Billing accounts* are commonly used for scenarios like grouping based on organizational constructs, invoice reconciliation and cost allocation strategies. -The BillingAccountId column MUST be present in the billing data. This column MUST be of type String and MUST NOT contain null values. BillingAccountId MUST be a globally unique identifier within a provider. +The BillingAccountId column MUST be present in a FOCUS dataset. This column MUST be of type String and MUST NOT contain null values. BillingAccountId MUST be a globally unique identifier within a provider. See [Appendix: Grouping constructs for resources or services](#groupingconstructsforresourcesorservices) for details and examples of the different grouping constructs supported by FOCUS. diff --git a/specification/columns/billingaccountname.md b/specification/columns/billingaccountname.md index 32a1b84e4..b5ced23e6 100644 --- a/specification/columns/billingaccountname.md +++ b/specification/columns/billingaccountname.md @@ -2,7 +2,7 @@ A Billing Account Name is a display name assigned to a [*billing account*](#glossary:billing-account). *Billing accounts* are commonly used for scenarios like grouping based on organizational constructs, invoice reconciliation and cost allocation strategies. -The BillingAccountName column MUST be present in the billing data and MUST NOT be null when the provider supports assigning a display name for the *billing account*. This column MUST be of type String. BillingAccountName MUST be unique within a customer when a customer has more than one *billing account*. +The BillingAccountName column MUST be present in a FOCUS dataset and MUST NOT be null when the provider supports assigning a display name for the *billing account*. This column MUST be of type String. BillingAccountName MUST be unique within a customer when a customer has more than one *billing account*. See [Appendix: Grouping constructs for resources or services](#groupingconstructsforresourcesorservices) for details and examples of the different grouping constructs supported by FOCUS. diff --git a/specification/columns/billingcurrency.md b/specification/columns/billingcurrency.md index df23adb1f..86ac91fa0 100644 --- a/specification/columns/billingcurrency.md +++ b/specification/columns/billingcurrency.md @@ -2,7 +2,7 @@ [*Billing currency*](#glossary:billing-currency) is an identifier that represents the currency that a charge for [*resources*](#glossary:resource) or [*services*](#glossary:service) was billed in. Billing Currency is commonly used in scenarios where costs need to be grouped or aggregated. -The BillingCurrency column MUST be present in the billing data. BillingCurrency MUST match the currency used in the invoice generated by the invoice issuer. This column MUST be of type String and MUST NOT contain null values. BillingCurrency MUST conform to [Currency Code Format](#currencycodeformat) requirements. +The BillingCurrency column MUST be present in a FOCUS dataset. BillingCurrency MUST match the currency used in the invoice generated by the invoice issuer. This column MUST be of type String and MUST NOT contain null values. BillingCurrency MUST conform to [Currency Code Format](#currencycodeformat) requirements. ## Column ID diff --git a/specification/columns/billingperiodend.md b/specification/columns/billingperiodend.md index df698ce88..9cd030e6d 100644 --- a/specification/columns/billingperiodend.md +++ b/specification/columns/billingperiodend.md @@ -2,7 +2,7 @@ Billing Period End represents the [*exclusive*](#glossary:exclusivebound) end date and time of a [*billing period*](#glossary:billing-period). For example, a time period where [BillingPeriodStart](#glossary:billingperiodstart) is '2024-01-01T00:00:00Z' and BillingPeriodEnd is '2024-02-01T00:00:00Z' includes charges for January, since BillingPeriodStart is [*inclusive*](#glossary:inclusivebound), but does not include charges for February since BillingPeriodEnd is *exclusive*. -The BillingPeriodEnd column MUST be present in the billing data. This column MUST be of type [Date/Time Format](#date/timeformat), MUST be an *exclusive* value, and MUST NOT contain null values. The sum of the [BilledCost](#billedcost) column for [*rows*](#glossary:row) in a given *billing period* MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account). +The BillingPeriodEnd column MUST be present in a FOCUS dataset. This column MUST be of type [Date/Time Format](#date/timeformat), MUST be an *exclusive* value, and MUST NOT contain null values. The sum of the [BilledCost](#billedcost) column for [*rows*](#glossary:row) in a given *billing period* MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account). ## Column ID diff --git a/specification/columns/billingperiodstart.md b/specification/columns/billingperiodstart.md index 27f125b8c..bc54163c5 100644 --- a/specification/columns/billingperiodstart.md +++ b/specification/columns/billingperiodstart.md @@ -2,7 +2,7 @@ Billing Period Start represents the [*inclusive*](#glossary:inclusivebound) start date and time of a [*billing period*](#glossary:billing-period). For example, a time period where BillingPeriodStart is '2024-01-01T00:00:00Z' and [BillingPeriodEnd](#billingperiodend) is '2024-02-01T00:00:00Z' includes charges for January, since BillingPeriodStart is inclusive, but does not include charges for February since BillingPeriodEnd is [*exclusive*](#glossary:exclusivebound). -The BillingPeriodStart column MUST be present in the billing data, MUST be of type [Date/Time Format](#date/timeformat), MUST be an *inclusive* value, and MUST NOT contain null values. The sum of the [BilledCost](#billedcost) metric for [*rows*](#glossary:row) in a given *billing period* MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account). +The BillingPeriodStart column MUST be present in a FOCUS dataset, MUST be of type [Date/Time Format](#date/timeformat), MUST be an *inclusive* value, and MUST NOT contain null values. The sum of the [BilledCost](#billedcost) metric for [*rows*](#glossary:row) in a given *billing period* MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account). ## Column ID diff --git a/specification/columns/chargecategory.md b/specification/columns/chargecategory.md index aec82092e..41f183c26 100644 --- a/specification/columns/chargecategory.md +++ b/specification/columns/chargecategory.md @@ -2,7 +2,7 @@ Charge Category represents the highest-level classification of a charge based on the nature of how it is billed. Charge Category is commonly used to identify and distinguish between types of charges that may require different handling. -The ChargeCategory column MUST be present in the billing data and MUST NOT be null. This column is of type String and MUST be one of the allowed values. +The ChargeCategory column MUST be present in a FOCUS dataset and MUST NOT be null. This column is of type String and MUST be one of the allowed values. ## Column ID diff --git a/specification/columns/chargeclass.md b/specification/columns/chargeclass.md index 9cd710888..e002ae33f 100644 --- a/specification/columns/chargeclass.md +++ b/specification/columns/chargeclass.md @@ -2,7 +2,7 @@ Charge Class indicates whether the row represents a correction to one or more [*charges*](#glossary:charge) invoiced in a previous billing period. Charge Class is commonly used to differentiate corrections from regularly incurred charges. -The ChargeClass column MUST be present in the billing data. This column MUST be of type String and MUST be "Correction" when the row represents a correction to one or more charges invoiced in a previous billing period. ChargeClass MUST be null when it is not a correction or when it is a correction within the current billing period. +The ChargeClass column MUST be present in a FOCUS dataset. This column MUST be of type String and MUST be "Correction" when the row represents a correction to one or more charges invoiced in a previous billing period. ChargeClass MUST be null when it is not a correction or when it is a correction within the current billing period. ## Column ID diff --git a/specification/columns/chargedescription.md b/specification/columns/chargedescription.md index dd6f5b58f..0f875c6e4 100644 --- a/specification/columns/chargedescription.md +++ b/specification/columns/chargedescription.md @@ -2,7 +2,7 @@ A Charge Description provides a high-level context of a [*row*](#glossary:row) without requiring additional discovery. This column is a self-contained summary of the charge's purpose and price. It typically covers a select group of corresponding details across a billing dataset or provides information not otherwise available. -The ChargeDescription column MUST be present in the billing data, MUST be of type String, and SHOULD NOT be null. Providers SHOULD specify the length of this column in their publicly available documentation. +The ChargeDescription column MUST be present in a FOCUS dataset, MUST be of type String, and SHOULD NOT be null. Providers SHOULD specify the length of this column in their publicly available documentation. ## Column ID diff --git a/specification/columns/chargefrequency.md b/specification/columns/chargefrequency.md index 3fa5319c1..45d94183c 100644 --- a/specification/columns/chargefrequency.md +++ b/specification/columns/chargefrequency.md @@ -2,7 +2,7 @@ Charge Frequency indicates how often a charge will occur. Along with the [charge period](#glossary:chargeperiod) related columns, the Charge Frequency is commonly used to understand recurrence periods (e.g., monthly, yearly), forecast upcoming charges, and differentiate between one-time and recurring fees for purchases. -The ChargeFrequency column is RECOMMENDED be present in the billing data and MUST NOT be null. This column is of type String and MUST be one of the allowed values. When [ChargeCategory](#chargecategory) is "Purchase", ChargeFrequency MUST NOT be "Usage-Based". +The ChargeFrequency column is RECOMMENDED be present in a FOCUS dataset and MUST NOT be null. This column is of type String and MUST be one of the allowed values. When [ChargeCategory](#chargecategory) is "Purchase", ChargeFrequency MUST NOT be "Usage-Based". ## Column ID diff --git a/specification/columns/chargeperiodend.md b/specification/columns/chargeperiodend.md index 053c905c9..c7e5060e8 100644 --- a/specification/columns/chargeperiodend.md +++ b/specification/columns/chargeperiodend.md @@ -2,7 +2,7 @@ Charge Period End represents the [*exclusive*](#glossary:exclusivebound) end date and time of a [*charge period*](#glossary:chargeperiod). For example, a time period where [ChargePeriodStart](#chargeperiodstart) is '2024-01-01T00:00:00Z' and ChargePeriodEnd is '2024-01-02T00:00:00Z' includes charges for January 1, since ChargePeriodStart is [*inclusive*](#glossary:inclusivebound), but does not include charges for January 2 since ChargePeriodEnd is *exclusive*. -ChargePeriodEnd MUST be present in the billing data, MUST be of type Date/Time, MUST be an *exclusive* value, and MUST NOT contain null values. ChargePeriodEnd MUST match the ending date and time boundary of the effective period of the charge. +ChargePeriodEnd MUST be present in a FOCUS dataset, MUST be of type Date/Time, MUST be an *exclusive* value, and MUST NOT contain null values. ChargePeriodEnd MUST match the ending date and time boundary of the effective period of the charge. ## Column ID diff --git a/specification/columns/chargeperiodstart.md b/specification/columns/chargeperiodstart.md index 18c8c9c5a..fe701b161 100644 --- a/specification/columns/chargeperiodstart.md +++ b/specification/columns/chargeperiodstart.md @@ -2,7 +2,7 @@ Charge Period Start represents the [*inclusive*](#glossary:inclusivebound) start date and time within a [*charge period*](#glossary:chargeperiod). For example, a time period where ChargePeriodStart is '2024-01-01T00:00:00Z' and [ChargePeriodEnd](#chargeperiodend) is '2024-01-02T00:00:00Z' includes charges for January 1, since ChargePeriodStart is *inclusive*, but does not include charges for January 2 since ChargePeriodEnd is [*exclusive*](#glossary:exclusivebound). -ChargePeriodStart MUST be present in the billing data, MUST be of type Date/Time, MUST be an *inclusive* value, and MUST NOT contain null values. ChargePeriodStart MUST match the beginning date and time boundary of the effective period of the charge. +ChargePeriodStart MUST be present in a FOCUS dataset, MUST be of type Date/Time, MUST be an *inclusive* value, and MUST NOT contain null values. ChargePeriodStart MUST match the beginning date and time boundary of the effective period of the charge. ## Column ID diff --git a/specification/columns/commitmentdiscountcategory.md b/specification/columns/commitmentdiscountcategory.md index cafcc4a51..7e422e9ee 100644 --- a/specification/columns/commitmentdiscountcategory.md +++ b/specification/columns/commitmentdiscountcategory.md @@ -2,7 +2,7 @@ Commitment Discount Category indicates whether the [*commitment-based discount*](#glossary:commitment-based-discount) identified in the CommitmentDiscountId column is based on usage quantity or cost (aka "spend"). -The CommitmentDiscountCategory column MUST be present in the billing data when the provider supports *commitment-based discounts*. This column MUST be of type String, MUST be null when [CommitmentDiscountId](#commitmentdiscountid) is null, and MUST NOT be null when CommitmentDiscountId is not null. The CommitmentDiscountCategory MUST be one of the allowed values. +The CommitmentDiscountCategory column MUST be present in a FOCUS dataset when the provider supports *commitment-based discounts*. This column MUST be of type String, MUST be null when [CommitmentDiscountId](#commitmentdiscountid) is null, and MUST NOT be null when CommitmentDiscountId is not null. The CommitmentDiscountCategory MUST be one of the allowed values. ## Column ID diff --git a/specification/columns/commitmentdiscountid.md b/specification/columns/commitmentdiscountid.md index 1824d5407..fd6a78bdf 100644 --- a/specification/columns/commitmentdiscountid.md +++ b/specification/columns/commitmentdiscountid.md @@ -2,7 +2,7 @@ A Commitment Discount ID is the identifier assigned to a [*commitment-based discount*](#glossary:commitment-based-discount) by the provider. Commitment Discount ID is commonly used for scenarios like chargeback for *commitments* and savings per *commitment-based discount*. -The CommitmentDiscountId column MUST be present in the billing data when the provider supports *commitment-based discounts*. This column MUST be of type String and MUST NOT contain null values when a charge is related to a *commitment-based discount*. When a charge is not associated with a *commitment-based discount*, the column MUST be null. CommitmentDiscountId MUST be unique within the provider. +The CommitmentDiscountId column MUST be present in a FOCUS dataset when the provider supports *commitment-based discounts*. This column MUST be of type String and MUST NOT contain null values when a charge is related to a *commitment-based discount*. When a charge is not associated with a *commitment-based discount*, the column MUST be null. CommitmentDiscountId MUST be unique within the provider. ## Column ID diff --git a/specification/columns/commitmentdiscountname.md b/specification/columns/commitmentdiscountname.md index 2b384b480..4ab4075ae 100644 --- a/specification/columns/commitmentdiscountname.md +++ b/specification/columns/commitmentdiscountname.md @@ -2,7 +2,7 @@ A Commitment Discount Name is the display name assigned to a [*commitment-based discount*](#glossary:commitment-based-discount). -The CommitmentDiscountName column MUST be present in the billing data when the provider supports *commitment-based discounts*. This column MUST be of type String. The CommitmentDiscountName value MUST be null if the charge is not related to a *commitment-based discount* and MAY be null if a display name cannot be assigned to a *commitment-based discount*. CommitmentDiscountName MUST NOT be null if a display name can be assigned to a *commitment-based discount*. +The CommitmentDiscountName column MUST be present in a FOCUS dataset when the provider supports *commitment-based discounts*. This column MUST be of type String. The CommitmentDiscountName value MUST be null if the charge is not related to a *commitment-based discount* and MAY be null if a display name cannot be assigned to a *commitment-based discount*. CommitmentDiscountName MUST NOT be null if a display name can be assigned to a *commitment-based discount*. ## Column ID diff --git a/specification/columns/commitmentdiscountstatus.md b/specification/columns/commitmentdiscountstatus.md index 31da82f9c..085e4417e 100644 --- a/specification/columns/commitmentdiscountstatus.md +++ b/specification/columns/commitmentdiscountstatus.md @@ -2,7 +2,7 @@ Commitment Discount Status indicates whether the charge corresponds with the consumption of the [*commitment-based discount*](#glossary:commitment-based-discount) identified in the CommitmentDiscountId column or the unused portion of the committed amount. -The CommitmentDiscountStatus column MUST be present in the billing data when the provider supports *commitment-based discounts*. This column MUST be of type String, MUST be null when [CommitmentDiscountId](#commitmentdiscountid) is null, and MUST NOT be null when CommitmentDiscountId is not null and [Charge Category](#chargecategory) is "Usage". The CommitmentDiscountCategory MUST be one of the allowed values. +The CommitmentDiscountStatus column MUST be present in a FOCUS dataset when the provider supports *commitment-based discounts*. This column MUST be of type String, MUST be null when [CommitmentDiscountId](#commitmentdiscountid) is null, and MUST NOT be null when CommitmentDiscountId is not null and [Charge Category](#chargecategory) is "Usage". The CommitmentDiscountCategory MUST be one of the allowed values. ## Column ID diff --git a/specification/columns/commitmentdiscounttype.md b/specification/columns/commitmentdiscounttype.md index 5a7ed12c7..71eb249c2 100644 --- a/specification/columns/commitmentdiscounttype.md +++ b/specification/columns/commitmentdiscounttype.md @@ -2,7 +2,7 @@ Commitment Discount Type is a provider-assigned name to identify the type of [*commitment-based discount*](#glossary:commitment-based-discount) applied to the [*row*](#glossary:row). -The CommitmentDiscountType column MUST be present in the billing data when the provider supports *commitment-based discounts*. This column MUST be of type String, MUST be null when [CommitmentDiscountId](#commitmentdiscountid) is null, and MUST NOT be null when CommitmentDiscountId is not null. +The CommitmentDiscountType column MUST be present in a FOCUS dataset when the provider supports *commitment-based discounts*. This column MUST be of type String, MUST be null when [CommitmentDiscountId](#commitmentdiscountid) is null, and MUST NOT be null when CommitmentDiscountId is not null. ## Column ID diff --git a/specification/columns/consumedquantity.md b/specification/columns/consumedquantity.md index 41f3763fb..faab3c0fa 100644 --- a/specification/columns/consumedquantity.md +++ b/specification/columns/consumedquantity.md @@ -2,7 +2,7 @@ The Consumed Quantity represents the volume of a given SKU associated with a [*resource*](#glossary:resource) or [*service*](#glossary:service) used, based on the [Consumed Unit](#consumedunit). Consumed Quantity is often derived at a finer granularity or over a different time interval when compared to the [Pricing Quantity](#pricingquantity) (complementary to [Pricing Unit](#pricingunit)) and focuses on *resource* and *service* consumption, not pricing and cost. -ConsumedQuantity column MUST be present in the billing data when the provider supports the measurement of usage. This column MUST NOT be null if [ChargeCategory](#chargecategory) is "Usage" and [ChargeClass](#chargeclass) is not "Correction". This column MUST be null for other ChargeCategory values. This column MUST be of type Decimal and MUST conform to [Numeric Format](#numericformat) requirements. The value MAY be negative in cases where [ChargeClass](#chargeclass) is "Correction". +ConsumedQuantity column MUST be present in a FOCUS dataset when the provider supports the measurement of usage. This column MUST NOT be null if [ChargeCategory](#chargecategory) is "Usage" and [ChargeClass](#chargeclass) is not "Correction". This column MUST be null for other ChargeCategory values. This column MUST be of type Decimal and MUST conform to [Numeric Format](#numericformat) requirements. The value MAY be negative in cases where [ChargeClass](#chargeclass) is "Correction". ## Column ID diff --git a/specification/columns/consumedunit.md b/specification/columns/consumedunit.md index f0f71870a..cb36de660 100644 --- a/specification/columns/consumedunit.md +++ b/specification/columns/consumedunit.md @@ -2,7 +2,7 @@ The Consumed Unit represents a provider-specified measurement unit indicating how a provider measures usage of a given SKU associated with a [*resource*](#glossary:resource) or [*service*](#glossary:service). Consumed Unit complements the [Consumed Quantity](#consumedquantity) metric. It is often listed at a finer granularity or over a different time interval when compared to [Pricing Unit](#pricingunit) (complementary to [Pricing Quantity](#pricingquantity)), and focuses on *resource* and *service* consumption, not pricing and cost. -The ConsumedUnit column MUST be present in the billing data when the provider supports the measurement of usage. This column MUST be of type String. ConsumedUnit MUST NOT be null if [ChargeCategory](#chargecategory) is "Usage" and [ChargeClass](#chargeclass) is not "Correction". This column MUST be null for other ChargeCategory values. Units of measure used in ConsumedUnit SHOULD adhere to the values and format requirements specified in the [UnitFormat](#unitformat) attribute. The ConsumedUnit column MUST NOT be used to determine values related to any pricing or cost metrics. +The ConsumedUnit column MUST be present in a FOCUS dataset when the provider supports the measurement of usage. This column MUST be of type String. ConsumedUnit MUST NOT be null if [ChargeCategory](#chargecategory) is "Usage" and [ChargeClass](#chargeclass) is not "Correction". This column MUST be null for other ChargeCategory values. Units of measure used in ConsumedUnit SHOULD adhere to the values and format requirements specified in the [UnitFormat](#unitformat) attribute. The ConsumedUnit column MUST NOT be used to determine values related to any pricing or cost metrics. ## Column ID diff --git a/specification/columns/contractedcost.md b/specification/columns/contractedcost.md index a43cf0a64..37710d034 100644 --- a/specification/columns/contractedcost.md +++ b/specification/columns/contractedcost.md @@ -4,7 +4,7 @@ Contracted Cost represents the cost calculated by multiplying [*contracted unit **Important:** When aggregating Contracted Cost for savings calculations, it's important to exclude either one-time or recurring charges ([Charge Category](#chargecategory) "Purchase") that are paid to cover future eligible charges (e.g., [Commitment-Based Discount](#glossary:commitment-based-discount)) or the covered charges themselves. This exclusion helps prevent double counting of these charges in the aggregation. Which set of charges to exclude depends on whether cost are aggregated on a billed basis (exclude covered charges) or accrual basis (exclude Purchases for future charges). For instance, charges categorized as [Charge Category](#chargecategory) "Purchase" and their related [Charge Category](#chargecategory) "Tax" charges for a Commitment-Based Discount might be excluded from an accrual basis cost aggregation of Contracted Cost. This is because the "Usage" and "Tax" charge records provided during the term of the commitment discount already specify the Contracted Cost. Purchase charges that cover future eligible charges can be identified by filtering for [Charge Category](#chargecategory) "Purchase" records with a [Billed Cost](#billedcost) greater than 0 and an [Effective Cost](#effectivecost) equal to 0. -The ContractedCost column MUST be present in the billing data and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. When [ContractedUnitPrice](#contractedunitprice) is present and not null, multiplying the ContractedUnitPrice by PricingQuantity MUST produce the ContractedCost, except in cases of [ChargeClass](#chargeclass) "Correction", which may address PricingQuantity or any cost discrepancies independently. +The ContractedCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. When [ContractedUnitPrice](#contractedunitprice) is present and not null, multiplying the ContractedUnitPrice by PricingQuantity MUST produce the ContractedCost, except in cases of [ChargeClass](#chargeclass) "Correction", which may address PricingQuantity or any cost discrepancies independently. In cases where the ContractedUnitPrice is present and null, the following applies: diff --git a/specification/columns/contractedunitprice.md b/specification/columns/contractedunitprice.md index 00eb8f4ce..0104c899a 100644 --- a/specification/columns/contractedunitprice.md +++ b/specification/columns/contractedunitprice.md @@ -2,7 +2,7 @@ The Contracted Unit Price represents the agreed-upon unit price for a single [Pricing Unit](#pricingunit) of the associated SKU, inclusive of negotiated discounts, if present, while excluding negotiated commitment-based discounts or any other discounts. This price is denominated in the [Billing Currency](#billingcurrency). The Contracted Unit Price is commonly used for calculating savings based on negotiation activities. If negotiated discounts are not applicable, the Contracted Unit Price defaults to the [List Unit Price](#listunitprice). -The ContractedUnitPrice column MUST be present in the billing data when the provider supports negotiated pricing concept. This column MUST be a Decimal within the range of non-negative decimal values, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When ContractedUnitPrice is present and not null, multiplying ContractedUnitPrice by [PricingQuantity](#pricingquantity) MUST equal [ContractedCost](#contractedcost), except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. +The ContractedUnitPrice column MUST be present in a FOCUS dataset when the provider supports negotiated pricing concept. This column MUST be a Decimal within the range of non-negative decimal values, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When ContractedUnitPrice is present and not null, multiplying ContractedUnitPrice by [PricingQuantity](#pricingquantity) MUST equal [ContractedCost](#contractedcost), except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. ## Column ID diff --git a/specification/columns/effectivecost.md b/specification/columns/effectivecost.md index 05ca41001..25c0f8ac7 100644 --- a/specification/columns/effectivecost.md +++ b/specification/columns/effectivecost.md @@ -7,7 +7,7 @@ This column resolves two challenges that are faced by practitioners: 1. Practitioners need to *amortize* relevant purchases, such as upfront fees, throughout the *commitment* and distribute them to the appropriate reporting groups (e.g. [*tags*](#glossary:tag), [*resources*](#glossary:resource)). 2. Many [*commitment-based discount*](#glossary:commitment-based-discount) constructs include a recurring expense for the *commitment* for every [*billing period*](#glossary:billing-period) and must distribute this cost to the *resources* using the *commitment*. This forces reconciliation between the initial *commitment* [*row*](#glossary:row) per period and the actual usage *rows*. -The EffectiveCost column MUST be present in the billing data and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. EffectiveCost MUST be 0 when ChargeCategory is "Purchase" and the purchase is intended to cover future eligible charges. The aggregated EffectiveCost for a billing period may not match the charge received on the invoice for the same *billing period*. +The EffectiveCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. EffectiveCost MUST be 0 when ChargeCategory is "Purchase" and the purchase is intended to cover future eligible charges. The aggregated EffectiveCost for a billing period may not match the charge received on the invoice for the same *billing period*. In cases where the [ChargeCategory](#chargecategory) is not "Usage" or "Purchase", the following applies: diff --git a/specification/columns/invoiceissuer.md b/specification/columns/invoiceissuer.md index a3a4382c4..7a1b76edf 100644 --- a/specification/columns/invoiceissuer.md +++ b/specification/columns/invoiceissuer.md @@ -3,7 +3,7 @@ An Invoice Issuer is an entity responsible for invoicing for the [*resources*](#glossary:resource) or [*services*](#glossary:service) consumed. It is commonly used for cost analysis and reporting scenarios. -The InvoiceIssuer column MUST be present in the billing data. This column MUST be of type String and MUST NOT contain null values. +The InvoiceIssuer column MUST be present in a FOCUS dataset. This column MUST be of type String and MUST NOT contain null values. See [Appendix: Origination of cost data](#originationofcostdata) section for examples of [Provider](#provider), [Publisher](#publisher) and Invoice Issuer values that can be used for various purchasing scenarios. diff --git a/specification/columns/listcost.md b/specification/columns/listcost.md index 083e76dcb..ad881ad3e 100644 --- a/specification/columns/listcost.md +++ b/specification/columns/listcost.md @@ -4,7 +4,7 @@ List Cost represents the cost calculated by multiplying the [*list unit price*]( **Important:** When aggregating List Cost for savings calculations, it's important to exclude either one-time or recurring charges ([Charge Category](#chargecategory) "Purchase") that are paid to cover future eligible charges (e.g., [Commitment-Based Discount](#glossary:commitment-based-discount)) or the covered charges themselves. This exclusion helps prevent double counting of these charges in the aggregation. Which set of charges to exclude depends on whether cost are aggregated on a billed basis (exclude covered charges) or accrual basis (exclude Purchases for future charges). For instance, charges categorized as [Charge Category](#chargecategory) "Purchase" and their related [Charge Category](#chargecategory) "Tax" charges for a Commitment-Based Discount might be excluded from an accrual basis cost aggregation of List Cost. This is because the "Usage" and "Tax" charge records provided during the term of the commitment discount already specify the List Cost. Purchase charges that cover future eligible charges can be identified by filtering for [Charge Category](#chargecategory) "Purchase" records with a [Billed Cost](#billedcost) greater than 0 and an [Effective Cost](#effectivecost) equal to 0. -The ListCost column MUST be present in the billing data and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. When [ListUnitPrice](#listunitprice) is present and not null, multiplying the ListUnitPrice by PricingQuantity MUST produce the ListCost, except in cases of [ChargeClass](#chargeclass) "Correction", which may address PricingQuantity or any cost discrepancies independently. +The ListCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. When [ListUnitPrice](#listunitprice) is present and not null, multiplying the ListUnitPrice by PricingQuantity MUST produce the ListCost, except in cases of [ChargeClass](#chargeclass) "Correction", which may address PricingQuantity or any cost discrepancies independently. In cases where the ListUnitPrice is present and is null, the following applies: diff --git a/specification/columns/listunitprice.md b/specification/columns/listunitprice.md index 7cab32e2d..531bd716c 100644 --- a/specification/columns/listunitprice.md +++ b/specification/columns/listunitprice.md @@ -2,7 +2,7 @@ The List Unit Price represents the suggested provider-published unit price for a single [Pricing Unit](#pricingunit) of the associated SKU, exclusive of any discounts. This price is denominated in the [Billing Currency](#billingcurrency). The List Unit Price is commonly used for calculating savings based on various rate optimization activities. -The ListUnitPrice column MUST be present in the billing data when the provider publishes unit prices exclusive of discounts. This column MUST be a Decimal within the range of non-negative decimal values, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When ListUnitPrice is present and is not null, multiplying ListUnitPrice by [PricingQuantity](#pricingquantity) MUST equal [ListCost](#listcost), except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. +The ListUnitPrice column MUST be present in a FOCUS dataset when the provider publishes unit prices exclusive of discounts. This column MUST be a Decimal within the range of non-negative decimal values, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When ListUnitPrice is present and is not null, multiplying ListUnitPrice by [PricingQuantity](#pricingquantity) MUST equal [ListCost](#listcost), except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. ## Column ID diff --git a/specification/columns/pricingcategory.md b/specification/columns/pricingcategory.md index 641b71074..c9037ec43 100644 --- a/specification/columns/pricingcategory.md +++ b/specification/columns/pricingcategory.md @@ -4,7 +4,7 @@ Pricing Category describes the pricing model used for a charge at the time of us The PricingCategory column adheres to the following requirements: -* PricingCategory MUST be present in the billing data when the provider supports more than one pricing category across all SKUs and MUST be of type String. +* PricingCategory MUST be present in a FOCUS dataset when the provider supports more than one pricing category across all SKUs and MUST be of type String. * PricingCategory MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. * PricingCategory MUST be one of the allowed values. * PricingCategory MUST be "Standard" when pricing is predetermined at the agreed upon rate for the [billing account](#glossary:billing-account). diff --git a/specification/columns/pricingquantity.md b/specification/columns/pricingquantity.md index f695c833c..b811cd71b 100644 --- a/specification/columns/pricingquantity.md +++ b/specification/columns/pricingquantity.md @@ -2,7 +2,7 @@ The Pricing Quantity represents the volume of a given SKU associated with a [*resource*](#glossary:resource) or [*service*](#glossary:service) used or purchased, based on the [Pricing Unit](#pricingunit). Distinct from [Consumed Quantity](#consumedquantity) (complementary to [Consumed Unit](#consumedunit)), it focuses on pricing and cost, not *resource* and *service* consumption. -The PricingQuantity column MUST be present in the billing data. This column MUST be of type Decimal and MUST conform to [Numeric Format](#numericformat) requirements. The value MAY be negative in cases where [ChargeClass](#chargeclass) is "Correction". This column MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When unit prices are not null, multiplying PricingQuantity by a unit price MUST produce a result equal to the corresponding cost metric, except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. +The PricingQuantity column MUST be present in a FOCUS dataset. This column MUST be of type Decimal and MUST conform to [Numeric Format](#numericformat) requirements. The value MAY be negative in cases where [ChargeClass](#chargeclass) is "Correction". This column MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When unit prices are not null, multiplying PricingQuantity by a unit price MUST produce a result equal to the corresponding cost metric, except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. ## Column ID diff --git a/specification/columns/pricingunit.md b/specification/columns/pricingunit.md index 5e283e6fa..73e38c943 100644 --- a/specification/columns/pricingunit.md +++ b/specification/columns/pricingunit.md @@ -2,7 +2,7 @@ The Pricing Unit represents a provider-specified measurement unit for determining unit prices, indicating how the provider rates measured usage and purchase quantities after applying pricing rules like [*block pricing*](#glossary:block-pricing). Common examples include the number of hours for compute appliance runtime (e.g. `Hours`), gigabyte-hours for a storage appliance (e.g., `GB-Hours`), or an accumulated count of requests for a network appliance or API service (e.g., `1000 Requests`). Pricing Unit complements the [Pricing Quantity](#pricingquantity) metric. Distinct from the [Consumed Unit](#Consumedunit), it focuses on pricing and cost, not [*resource*](#glossary:resource) and [*service*](#glossary:service) consumption, often at a coarser granularity. -The PricingUnit column MUST be present in the billing data. This column MUST be of type String. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. Units of measure used in PricingUnit SHOULD adhere to the values and format requirements specified in the [UnitFormat](#unitformat) attribute. +The PricingUnit column MUST be present in a FOCUS dataset. This column MUST be of type String. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. Units of measure used in PricingUnit SHOULD adhere to the values and format requirements specified in the [UnitFormat](#unitformat) attribute. The PricingUnit value MUST be semantically equal to the corresponding pricing measurement unit value provided in: diff --git a/specification/columns/provider.md b/specification/columns/provider.md index ff772f70c..e17f43e90 100644 --- a/specification/columns/provider.md +++ b/specification/columns/provider.md @@ -2,7 +2,7 @@ A Provider is an entity that makes the [*resources*](#glossary:resource) or [*services*](#glossary:service) available for purchase. It is commonly used for cost analysis and reporting scenarios. -The Provider column MUST be present in the billing data. This column MUST be of type String and MUST NOT contain null values. +The Provider column MUST be present in a FOCUS dataset. This column MUST be of type String and MUST NOT contain null values. See [Appendix: Origination of cost data](#originationofcostdata) section for examples of Provider, Publisher and Invoice Issuer values that can be used for various purchasing scenarios. diff --git a/specification/columns/publisher.md b/specification/columns/publisher.md index 827b19014..a9f5fd16c 100644 --- a/specification/columns/publisher.md +++ b/specification/columns/publisher.md @@ -2,7 +2,7 @@ A Publisher is an entity that produces the [*resources*](#glossary:resource) or [*services*](#glossary:service) that were purchased. It is commonly used for cost analysis and reporting scenarios. -The Publisher column MUST be present in the billing data. This column MUST be of type String and MUST NOT contain null values. +The Publisher column MUST be present in a FOCUS dataset. This column MUST be of type String and MUST NOT contain null values. See [Appendix: Origination of cost data](#originationofcostdata) section for examples of [Provider](#provider), Publisher and [Invoice Issuer](#invoiceissuer) values that can be used for various purchasing scenarios. diff --git a/specification/columns/regionid.md b/specification/columns/regionid.md index 06742553d..873d036df 100644 --- a/specification/columns/regionid.md +++ b/specification/columns/regionid.md @@ -2,7 +2,7 @@ A Region ID is a provider-assigned identifier for an isolated geographic area where a [*resource*](#glossary:resource) is provisioned or a [*service*](#glossary:service) is provided. The region is commonly used for scenarios like analyzing cost and unit prices based on where *resources* are deployed. -The RegionId column MUST be present in the billing data when the provider supports deploying resources or services within a *region* and MUST be of type String. RegionId MUST NOT be null when a *resource* or *service* is operated in or managed from a distinct region by the Provider and MAY contain null values when a *resource* or *service* is not restricted to an isolated geographic area. +The RegionId column MUST be present in a FOCUS dataset when the provider supports deploying resources or services within a *region* and MUST be of type String. RegionId MUST NOT be null when a *resource* or *service* is operated in or managed from a distinct region by the Provider and MAY contain null values when a *resource* or *service* is not restricted to an isolated geographic area. ## Column ID diff --git a/specification/columns/regionname.md b/specification/columns/regionname.md index 40d030876..934ca0b91 100644 --- a/specification/columns/regionname.md +++ b/specification/columns/regionname.md @@ -2,7 +2,7 @@ Region Name is a provider-assigned display name for an isolated geographic area where a [*resource*](#glossary:resource) is provisioned or a [*service*](#glossary:service) is provided. Region Name is commonly used for scenarios like analyzing cost and unit prices based on where *resources* are deployed. -The RegionName column MUST be present in the billing data when the provider supports deploying resources or services within a *region* and MUST be of type String. RegionName MUST NOT be null when a *resource* or *service* is operated in or managed from a distinct region by the Provider and MAY contain null values when a *resource* or *service* is not restricted to an isolated geographic area. +The RegionName column MUST be present in a FOCUS dataset when the provider supports deploying resources or services within a *region* and MUST be of type String. RegionName MUST NOT be null when a *resource* or *service* is operated in or managed from a distinct region by the Provider and MAY contain null values when a *resource* or *service* is not restricted to an isolated geographic area. ## Column ID diff --git a/specification/columns/resourceid.md b/specification/columns/resourceid.md index 85bd08058..e48d24d08 100644 --- a/specification/columns/resourceid.md +++ b/specification/columns/resourceid.md @@ -2,7 +2,7 @@ A Resource ID is an identifier assigned to a [*resource*](#glossary:resource) by the provider. The Resource ID is commonly used for cost reporting, analysis, and allocation scenarios. -The ResourceId column MUST be present in the billing data when the provider supports billing based on provisioned resources. This column MUST be of type String. The ResourceId value MAY be a nullable column as some cost data [*rows*](#glossary:row) may not be associated with a *resource*. ResourceId MUST appear in the cost data if an identifier is assigned to a *resource* by the provider. ResourceId SHOULD be a fully-qualified identifier that ensures global uniqueness within the provider. +The ResourceId column MUST be present in a FOCUS dataset when the provider supports billing based on provisioned resources. This column MUST be of type String. The ResourceId value MAY be a nullable column as some cost data [*rows*](#glossary:row) may not be associated with a *resource*. ResourceId MUST appear in the cost data if an identifier is assigned to a *resource* by the provider. ResourceId SHOULD be a fully-qualified identifier that ensures global uniqueness within the provider. ## Column ID diff --git a/specification/columns/resourcename.md b/specification/columns/resourcename.md index 4ebf817bc..524311b0c 100644 --- a/specification/columns/resourcename.md +++ b/specification/columns/resourcename.md @@ -2,7 +2,7 @@ The Resource Name is a display name assigned to a [*resource*](#glossary:resource). It is commonly used for cost analysis, reporting, and allocation scenarios. -The ResourceName column MUST be present in the billing data when the provider supports billing based on provisioned resources. This column MUST be of type String. The ResourceName value MAY be a nullable column as some cost data [*rows*](#glossary:row) may not be associated with a *resource* or because a display name cannot be assigned to a *resource*. ResourceName MUST NOT be null if a display name can be assigned to a *resource*. *Resources* not provisioned interactively or only have a system-generated [ResourceId](#resourceid) MUST NOT duplicate the same value as the ResourceName. +The ResourceName column MUST be present in a FOCUS dataset when the provider supports billing based on provisioned resources. This column MUST be of type String. The ResourceName value MAY be a nullable column as some cost data [*rows*](#glossary:row) may not be associated with a *resource* or because a display name cannot be assigned to a *resource*. ResourceName MUST NOT be null if a display name can be assigned to a *resource*. *Resources* not provisioned interactively or only have a system-generated [ResourceId](#resourceid) MUST NOT duplicate the same value as the ResourceName. ## Column ID diff --git a/specification/columns/resourcetype.md b/specification/columns/resourcetype.md index 605d707aa..96480f78a 100644 --- a/specification/columns/resourcetype.md +++ b/specification/columns/resourcetype.md @@ -2,7 +2,7 @@ Resource Type describes the kind of [*resource*](#glossary:resource) the charge applies to. A Resource Type is commonly used for scenarios like identifying cost changes in groups of similar *resources* and may include values like Virtual Machine, Data Warehouse, and Load Balancer. -The ResourceType column MUST be present in the billing data when the provider supports billing based on provisioned resources and supports assigning a type for resources. This column MUST be of type String and MUST NOT be null when a corresponding [ResourceId](#resourceid) is not null. When a corresponding ResourceId value is null, the ResourceType column value MUST also be null. +The ResourceType column MUST be present in a FOCUS dataset when the provider supports billing based on provisioned resources and supports assigning a type for resources. This column MUST be of type String and MUST NOT be null when a corresponding [ResourceId](#resourceid) is not null. When a corresponding ResourceId value is null, the ResourceType column value MUST also be null. ## Column ID diff --git a/specification/columns/servicecategory.md b/specification/columns/servicecategory.md index 1ee72a960..c8d474fbb 100644 --- a/specification/columns/servicecategory.md +++ b/specification/columns/servicecategory.md @@ -2,7 +2,7 @@ The Service Category is the highest-level classification of a [*service*](#glossary:service) based on the core function of the *service*. Each *service* should have one and only one category that best aligns with its primary purpose. The Service Category is commonly used for scenarios like analyzing costs across providers and tracking the migration of workloads across fundamentally different architectures. -The ServiceCategory column MUST be present and MUST NOT be null. This column is of type String and MUST be one of the allowed values. +The ServiceCategory column MUST be present in a FOCUS dataset and MUST NOT be null. This column is of type String and MUST be one of the allowed values. ## Column ID diff --git a/specification/columns/servicename.md b/specification/columns/servicename.md index 0f4ab9547..db1fc0cda 100644 --- a/specification/columns/servicename.md +++ b/specification/columns/servicename.md @@ -4,7 +4,7 @@ A [*service*](#glossary:service) represents an offering that can be purchased fr The Service Name is a display name for the offering that was purchased. The Service Name is commonly used for scenarios like analyzing aggregate cost trends over time and filtering data to investigate anomalies. -The ServiceName column MUST be present in the cost data. This column MUST be of type String and MUST NOT contain null values. +The ServiceName column MUST be present in a FOCUS dataset. This column MUST be of type String and MUST NOT contain null values. ## Column ID diff --git a/specification/columns/skuid.md b/specification/columns/skuid.md index 5a4a93f1a..7ab6ce38d 100644 --- a/specification/columns/skuid.md +++ b/specification/columns/skuid.md @@ -2,7 +2,7 @@ A SKU ID is a unique identifier that defines a provider-supported construct for organizing properties that are common across one or more [*SKU Prices*](#glossary:sku-price). SKU ID can be referenced on a catalog or [*price list*](#glossary:price-list) published by a provider to look up detailed information about the SKU. The composition of the properties associated with the SKU ID may differ across providers. Some providers may not support the [*SKU*](#glossary:sku) construct and instead associate all such properties directly with the *SKU Price*. SKU ID is commonly used for analyzing cost based on *SKU*-related properties above the pricing constructs. -The SkuId column MUST be present in the billing data when the provider publishes a SKU list. This column MUST be of type String. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. SkuId MUST equal SkuPriceId when a provider does not support an overarching SKU ID construct. +The SkuId column MUST be present in a FOCUS dataset when the provider publishes a SKU list. This column MUST be of type String. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. SkuId MUST equal SkuPriceId when a provider does not support an overarching SKU ID construct. ## Column ID diff --git a/specification/columns/skupriceid.md b/specification/columns/skupriceid.md index 3c5ad2bf2..2dad50bc1 100644 --- a/specification/columns/skupriceid.md +++ b/specification/columns/skupriceid.md @@ -2,7 +2,7 @@ A SKU Price ID is a unique identifier that defines the unit price used to calculate the charge. SKU Price ID can be referenced on a [*price list*](#glossary:price-list) published by a provider to look up detailed information, including a corresponding list unit price. The composition of the properties associated with the SKU Price ID may differ across providers. SKU Price ID is commonly used for analyzing cost based on pricing properties such as Terms and Tiers. -The SkuPriceId column MUST be present in the billing data when the provider publishes a SKU price list. This column MUST be of type String. SkuPriceId MUST define a single unit price used for calculating the charge. The [ListUnitPrice](#listunitprice) MUST be associated with the SkuPriceId in the provider published *price list*. This column MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. A given value of SkuPriceId MUST be associated with one and only one [SkuId](#skuid), except in cases of commitment discount flexibility. +The SkuPriceId column MUST be present in a FOCUS dataset when the provider publishes a SKU price list. This column MUST be of type String. SkuPriceId MUST define a single unit price used for calculating the charge. The [ListUnitPrice](#listunitprice) MUST be associated with the SkuPriceId in the provider published *price list*. This column MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. A given value of SkuPriceId MUST be associated with one and only one [SkuId](#skuid), except in cases of commitment discount flexibility. ## Column ID diff --git a/specification/columns/subaccountid.md b/specification/columns/subaccountid.md index 9f85ffda2..f0bfd2a4a 100644 --- a/specification/columns/subaccountid.md +++ b/specification/columns/subaccountid.md @@ -2,7 +2,7 @@ A Sub Account ID is a provider-assigned identifier assigned to a [*sub account*](#glossary:sub-account). Sub Account ID is commonly used for scenarios like grouping based on organizational constructs, access management needs, and cost allocation strategies. -The SubAccountId column MUST be present in the billing data when the provider supports a *sub account* construct. This column MUST be of type String. If a charge does not apply to a *sub account*, the SubAccountId column MUST be null. +The SubAccountId column MUST be present in a FOCUS dataset when the provider supports a *sub account* construct. This column MUST be of type String. If a charge does not apply to a *sub account*, the SubAccountId column MUST be null. See [Appendix: Grouping constructs for resources or services](#groupingconstructsforresourcesorservices) for details and examples of the different grouping constructs supported by FOCUS. diff --git a/specification/columns/subaccountname.md b/specification/columns/subaccountname.md index e5428658d..0f837ecec 100644 --- a/specification/columns/subaccountname.md +++ b/specification/columns/subaccountname.md @@ -2,7 +2,7 @@ A Sub Account Name is a display name assigned to a [*sub account*](#glossary:sub-account). Sub account Name is commonly used for scenarios like grouping based on organizational constructs, access management needs, and cost allocation strategies. -The SubAccountName column MUST be present in the billing data when the provider supports a *sub account* construct. This column MUST be of type String. If a charge does not apply to a *sub account*, the SubAccountName column MUST be null. +The SubAccountName column MUST be present in a FOCUS dataset when the provider supports a *sub account* construct. This column MUST be of type String. If a charge does not apply to a *sub account*, the SubAccountName column MUST be null. See [Appendix: Grouping constructs for resources or services](#groupingconstructsforresourcesorservices) for details and examples of the different grouping constructs supported by FOCUS. diff --git a/specification/columns/tags.md b/specification/columns/tags.md index 3795f8139..f97b75d92 100644 --- a/specification/columns/tags.md +++ b/specification/columns/tags.md @@ -1,12 +1,12 @@ # Tags -The Tags column represents the set of tags assigned to [*tag sources*](#glossary:tag-source) that also account for potential provider-defined or user-defined tag evaluations. Tags are commonly used for scenarios like adding business context to billing data to identify and accurately allocate charges. Tags may also be referred to by providers using other terms such as labels. +The Tags column represents the set of tags assigned to [*tag sources*](#glossary:tag-source) that also account for potential provider-defined or user-defined tag evaluations. Tags are commonly used for scenarios like adding business context to cost and usage data to identify and accurately allocate charges. Tags may also be referred to by providers using other terms such as labels. A tag becomes [*finalized*](#glossary:finalized-tag) when a single value is selected from a set of possible tag values assigned to the tag key. When supported by a provider, this can occur when a tag value is set by provider-defined or user-defined rules. The Tags column adheres to the following requirements: -* The Tags column MUST be present in the billing data when the provider supports setting user or provider-defined tags. +* The Tags column MUST be present in a FOCUS dataset when the provider supports setting user or provider-defined tags. * The Tags column MUST contain user-defined and provider-defined tags. * The Tags column MUST only contain finalized tags. * The Tags column MUST be in [Key-Value Format](#key-valueformat). @@ -46,7 +46,7 @@ As an example, let's assume 1 [*sub account*](#glossary:sub-account) exists with * id: *my-vm* * user-defined tags: *team:web* -The table below represents a finalized billing dataset with these *resources*. It also shows the finalized state after all resource-oriented, tag inheritance rules are processed. +The table below represents a finalized dataset with these *resources*. It also shows the finalized state after all resource-oriented, tag inheritance rules are processed. | ResourceType | ResourceId | Tags | | :---------------| :--------------| :-------------------------------------------| diff --git a/specification/glossary.md b/specification/glossary.md index 7c11aeec0..677b138d6 100644 --- a/specification/glossary.md +++ b/specification/glossary.md @@ -76,6 +76,10 @@ A tag with one tag value chosen from a set of possible tag values after being pr An open-source specification that defines requirements for billing data. +FOCUS Dataset + +A structured collection of cost and usage data that meets or exceeds the Basic compliance criteria of FOCUS. + Inclusive Bound A Date/Time Format value that is contained within the beginning bound of a time period. From ee959e1f6a9c123f514ae577f0d69a74b22c2ce1 Mon Sep 17 00:00:00 2001 From: Irena Jurica Date: Sat, 3 Aug 2024 16:37:56 +0200 Subject: [PATCH 16/52] FOCUS #491: ChargeClass - 'Corrections' as a result of late arriving charge records (#505) Specification and supporting content update. In case of late arriving costs, there might not be previous charges that we are explicitly correcting, but rather correcting the invoiced billing period as a whole. Co-authored-by: Joaquin Co-authored-by: Christopher Harris --- specification/columns/chargeclass.md | 8 ++++---- supporting_content/columns/chargeclass.md | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/specification/columns/chargeclass.md b/specification/columns/chargeclass.md index e002ae33f..41866810e 100644 --- a/specification/columns/chargeclass.md +++ b/specification/columns/chargeclass.md @@ -1,8 +1,8 @@ # Charge Class -Charge Class indicates whether the row represents a correction to one or more [*charges*](#glossary:charge) invoiced in a previous billing period. Charge Class is commonly used to differentiate corrections from regularly incurred charges. +Charge Class indicates whether the row represents a correction to a previously invoiced [*billing period*](#glossary:billing-period). Charge Class is commonly used to differentiate corrections from regularly incurred charges. -The ChargeClass column MUST be present in a FOCUS dataset. This column MUST be of type String and MUST be "Correction" when the row represents a correction to one or more charges invoiced in a previous billing period. ChargeClass MUST be null when it is not a correction or when it is a correction within the current billing period. +The ChargeClass column MUST be present in the FOCUS dataset. This column MUST be of type String and MUST be "Correction" when the row represents a correction to a previously invoiced *billing period*. ChargeClass MUST be null when it is not a correction or when it is a correction within the current *billing period*. ## Column ID @@ -14,7 +14,7 @@ Charge Class ## Description -Indicates whether the row represents a correction to one or more *charges* invoiced in a previous billing period. +Indicates whether the row represents a correction to a previously invoiced *billing period*. ## Content Constraints @@ -30,7 +30,7 @@ Allowed values: | Value | Description | | :--------- | :------------------------------------| -| Correction | Correction to one or more charges invoiced in previous billing periods (e.g., refunds and credit modifications). | +| Correction | Correction to a previously invoiced *billing period* (e.g., refunds and credit modifications). | ## Introduced (version) diff --git a/supporting_content/columns/chargeclass.md b/supporting_content/columns/chargeclass.md index be91dbc8d..4297801d7 100644 --- a/supporting_content/columns/chargeclass.md +++ b/supporting_content/columns/chargeclass.md @@ -6,7 +6,7 @@ * Initially, ChargeClass was defined as a non-nullable column with two allowed values: Regular and Correction. * Various alternative names for Regular charges were discussed, including Regular, Standard, Original, and Direct. -* Eventually, the team decided on a nullable column approach, where Correction is the sole allowed value, representing corrections to one or more charges invoiced in a previous billing period. +* Eventually, the team decided on a nullable column approach, where Correction is the sole allowed value, representing corrections to a previously invoiced billing period. ### Impacts of 1.0 ChargeCategory and ChargeClass cleanup From 4c56081a47410b450896bb93438e861467c601e2 Mon Sep 17 00:00:00 2001 From: Joaquin Date: Tue, 20 Aug 2024 11:35:41 +0200 Subject: [PATCH 17/52] Rename spec_change.yml to spec-change.yml --- .github/ISSUE_TEMPLATE/{spec_change.yml => spec-change.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/ISSUE_TEMPLATE/{spec_change.yml => spec-change.yml} (100%) diff --git a/.github/ISSUE_TEMPLATE/spec_change.yml b/.github/ISSUE_TEMPLATE/spec-change.yml similarity index 100% rename from .github/ISSUE_TEMPLATE/spec_change.yml rename to .github/ISSUE_TEMPLATE/spec-change.yml From 5f86e458da093bcecfbde2e4e188180a6d452c0f Mon Sep 17 00:00:00 2001 From: Christopher Harris Date: Fri, 23 Aug 2024 03:42:23 -0400 Subject: [PATCH 18/52] Remove incorrect mention of 'Charge Subcategory' and correct with 'Charge Category' (#527) Since 'Charge Subcategory' was rolled up into 'Charge Category', remove all references. --- specification/attributes/discount_handling.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/attributes/discount_handling.md b/specification/attributes/discount_handling.md index aa48d8f1b..87770e053 100644 --- a/specification/attributes/discount_handling.md +++ b/specification/attributes/discount_handling.md @@ -6,7 +6,7 @@ Some discount offers can be purchased from a provider to get reduced prices. The Amortization is a process used to break down and spread purchase costs over a period of time or term of use. When a purchase is applicable to resources, like commitment-based discounts, the amortized cost of a resource takes the initial payment and term into account and distributes it out based on the resource's usage, attributing the prorated cost for each unit of billing. Amortization enables users of billing data to distribute purchase charges to the appropriate audience in support of cost allocation efforts. Discount Handling for purchased commitments is commonly used for scenarios like calculating utilization and implementing chargeback for the purchase amount. -While providers may use different terms to describe discounts, FOCUS identifies a discount as being a reduced price applied directly to a row. Any price or cost reductions that are awarded after the fact are identified as a "Credit" Charge Subcategory. One example might be when a provider offers a reduced rate after passing a certain threshold of usage or spend. +While providers may use different terms to describe discounts, FOCUS identifies a discount as being a reduced price applied directly to a row. Any price or cost reductions that are awarded after the fact are identified as a "Credit" Charge Category. One example might be when a provider offers a reduced rate after passing a certain threshold of usage or spend. All rows defined in FOCUS MUST follow the discount handling requirements listed below. From e07c9fc655930bf5deebd538c13fbf1acf420400 Mon Sep 17 00:00:00 2001 From: Christopher Harris Date: Fri, 23 Aug 2024 12:41:10 -0400 Subject: [PATCH 19/52] Rename all mentions on "commitment-based discount" (or similar) to "commitment discount" (or similar) to match updated iteration of term in FinOps Terminology page. (#524) Rename all mentions on "commitment-based discount" (or similar) to "commitment discount" (or similar) to match updated iteration of term in FinOps Terminology page: https://www.finops.org/assets/terminology/#commitment-discounts image Co-authored-by: Joaquin --- specification/attributes/discount_handling.md | 16 ++++++++-------- .../columns/commitmentdiscountcategory.md | 10 +++++----- specification/columns/commitmentdiscountid.md | 6 +++--- specification/columns/commitmentdiscountname.md | 6 +++--- .../columns/commitmentdiscountstatus.md | 10 +++++----- specification/columns/commitmentdiscounttype.md | 6 +++--- specification/columns/contractedcost.md | 2 +- specification/columns/contractedunitprice.md | 4 ++-- specification/columns/effectivecost.md | 2 +- specification/columns/listcost.md | 2 +- specification/columns/pricingcategory.md | 6 +++--- specification/glossary.md | 2 +- specification/use_case_library.md | 8 ++++---- .../attributes/discount_handling.md | 4 ++-- supporting_content/columns/chargecategory.md | 2 +- .../columns/contractedunitprice.md | 2 +- supporting_content/columns/listunitprice.md | 4 ++-- supporting_content/columns/pricingcategory.md | 4 ++-- supporting_content/columns/pricingquantity.md | 2 +- 19 files changed, 49 insertions(+), 49 deletions(-) diff --git a/specification/attributes/discount_handling.md b/specification/attributes/discount_handling.md index 87770e053..be585c284 100644 --- a/specification/attributes/discount_handling.md +++ b/specification/attributes/discount_handling.md @@ -1,10 +1,10 @@ # Discount Handling -A discount is a pricing construct where providers offer a reduced price for [*services*](#glossary:service). Providers may have many types of discounts, including but not limited to commercially negotiated discounts, commitment-based discounts when you agree to a certain amount of usage or spend, and bundled discounts where you receive free or discounted usage of one product or *service* based on the usage of another. Discount Handling is commonly used in scenarios like verifying discounts were applied and calculating cost savings. +A discount is a pricing construct where providers offer a reduced price for [*services*](#glossary:service). Providers may have many types of discounts, including but not limited to commercially negotiated discounts, commitment discounts when you agree to a certain amount of usage or spend, and bundled discounts where you receive free or discounted usage of one product or *service* based on the usage of another. Discount Handling is commonly used in scenarios like verifying discounts were applied and calculating cost savings. -Some discount offers can be purchased from a provider to get reduced prices. The most common example is a commitment-based discount, where you "purchase" a commitment to use or spend a specific amount within a period. When a commitment isn't fully utilized, the unused amount reduces the potential savings from the discount and can even result in paying higher costs than without the discount. Due to this risk, unused commitment amounts need to be clearly identifiable at a granular level. To facilitate this, unused commitments are recorded with a separate row for each charge period where the commitment was not fully utilized. In order to show the impact of purchased discounts on each discounted row, discount purchases need the purchase amount the be amortized over the term the discount is applied to (e.g., 1 year) with each charge period split and applied to each row that received the discount. +Some discount offers can be purchased from a provider to get reduced prices. The most common example is a commitment discount, where you "purchase" a commitment to use or spend a specific amount within a period. When a commitment isn't fully utilized, the unused amount reduces the potential savings from the discount and can even result in paying higher costs than without the discount. Due to this risk, unused commitment amounts need to be clearly identifiable at a granular level. To facilitate this, unused commitments are recorded with a separate row for each charge period where the commitment was not fully utilized. In order to show the impact of purchased discounts on each discounted row, discount purchases need the purchase amount the be amortized over the term the discount is applied to (e.g., 1 year) with each charge period split and applied to each row that received the discount. -Amortization is a process used to break down and spread purchase costs over a period of time or term of use. When a purchase is applicable to resources, like commitment-based discounts, the amortized cost of a resource takes the initial payment and term into account and distributes it out based on the resource's usage, attributing the prorated cost for each unit of billing. Amortization enables users of billing data to distribute purchase charges to the appropriate audience in support of cost allocation efforts. Discount Handling for purchased commitments is commonly used for scenarios like calculating utilization and implementing chargeback for the purchase amount. +Amortization is a process used to break down and spread purchase costs over a period of time or term of use. When a purchase is applicable to resources, like commitment discounts, the amortized cost of a resource takes the initial payment and term into account and distributes it out based on the resource's usage, attributing the prorated cost for each unit of billing. Amortization enables users of billing data to distribute purchase charges to the appropriate audience in support of cost allocation efforts. Discount Handling for purchased commitments is commonly used for scenarios like calculating utilization and implementing chargeback for the purchase amount. While providers may use different terms to describe discounts, FOCUS identifies a discount as being a reduced price applied directly to a row. Any price or cost reductions that are awarded after the fact are identified as a "Credit" Charge Category. One example might be when a provider offers a reduced rate after passing a certain threshold of usage or spend. @@ -29,15 +29,15 @@ Indicates how to include and apply discounts to usage charges or rows in a FOCUS * Multiple discounts MAY apply to a row, but they MUST apply to the entire charge covered by that row. * If a discount only applies to a portion of a charge, then the discounted portion of the charge MUST be split into a separate row. * Each discount MUST be identifiable using existing FOCUS columns. - * Rows with a commitment-based discount applied to them MUST include a CommitmentDiscountId. + * Rows with a commitment discount applied to them MUST include a CommitmentDiscountId. * If a provider applies a discount that cannot be represented by a FOCUS column, they SHOULD include additional columns to identify the source of the discount. -* Purchased discounts (e.g., commitment-based discounts) MUST be amortized. +* Purchased discounts (e.g., commitment discounts) MUST be amortized. * The BilledCost MUST be 0 for any row where the commitment covers the entire cost for the charge period. * The EffectiveCost MUST include the portion of the amortized purchase cost that applies to this row. - * The sum of the EffectiveCost for all rows where CommitmentDiscountStatus is "Used" or "Unused" for each CommitmentDiscountId over the entire duration of the commitment MUST be the same as the total BilledCost of the commitment-based discount. - * The CommitmentDiscountId and ResourceId MUST be set to the ID assigned to the commitment-based discount. ChargeCategory MUST be set to "Purchase" on rows that represent a purchase of a commitment-based discount. + * The sum of the EffectiveCost for all rows where CommitmentDiscountStatus is "Used" or "Unused" for each CommitmentDiscountId over the entire duration of the commitment MUST be the same as the total BilledCost of the commitment discount. + * The CommitmentDiscountId and ResourceId MUST be set to the ID assigned to the commitment discount. ChargeCategory MUST be set to "Purchase" on rows that represent a purchase of a commitment discount. * CommitmentDiscountStatus MUST be "Used" for ChargeCategory "Usage" rows that received a reduced price from a commitment. CommitmentDiscountId MUST be set to the ID assigned to the discount. ResourceId MUST be set to the ID of the resource that received the discount. - * If a commitment is not fully utilized, the provider MUST include a row that represents the unused portion of the commitment for that charge period. These rows MUST be represented with CommitmentDiscountStatus set to "Unused" and ChargeCategory set to "Usage". Such rows MUST have their CommitmentDiscountId and ResourceId set to the ID assigned to the commitment-based discount. + * If a commitment is not fully utilized, the provider MUST include a row that represents the unused portion of the commitment for that charge period. These rows MUST be represented with CommitmentDiscountStatus set to "Unused" and ChargeCategory set to "Usage". Such rows MUST have their CommitmentDiscountId and ResourceId set to the ID assigned to the commitment discount. * Credits that are applied after the fact MUST use a ChargeCategory of "Credit". ## Exceptions diff --git a/specification/columns/commitmentdiscountcategory.md b/specification/columns/commitmentdiscountcategory.md index 7e422e9ee..70c08b180 100644 --- a/specification/columns/commitmentdiscountcategory.md +++ b/specification/columns/commitmentdiscountcategory.md @@ -1,8 +1,8 @@ # Commitment Discount Category -Commitment Discount Category indicates whether the [*commitment-based discount*](#glossary:commitment-based-discount) identified in the CommitmentDiscountId column is based on usage quantity or cost (aka "spend"). +Commitment Discount Category indicates whether the [*commitment discount*](#glossary:commitment-discount) identified in the CommitmentDiscountId column is based on usage quantity or cost (aka "spend"). -The CommitmentDiscountCategory column MUST be present in a FOCUS dataset when the provider supports *commitment-based discounts*. This column MUST be of type String, MUST be null when [CommitmentDiscountId](#commitmentdiscountid) is null, and MUST NOT be null when CommitmentDiscountId is not null. The CommitmentDiscountCategory MUST be one of the allowed values. +The CommitmentDiscountCategory column MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. This column MUST be of type String, MUST be null when [CommitmentDiscountId](#commitmentdiscountid) is null, and MUST NOT be null when CommitmentDiscountId is not null. The CommitmentDiscountCategory MUST be one of the allowed values. ## Column ID @@ -14,7 +14,7 @@ Commitment Discount Category ## Description -Indicates whether the *commitment-based discount* identified in the CommitmentDiscountId column is based on usage quantity or cost (aka "spend"). +Indicates whether the *commitment discount* identified in the CommitmentDiscountId column is based on usage quantity or cost (aka "spend"). ## Content constraints @@ -30,8 +30,8 @@ Allowed values: | Value | Description | |:--------|:-------------------------------------------------------------------------| -| Spend | Commitment-based discounts that require a predetermined amount of spend. | -| Usage | Commitment-based discounts that require a predetermined amount of usage. | +| Spend | Commitment discounts that require a predetermined amount of spend. | +| Usage | Commitment discounts that require a predetermined amount of usage. | ## Introduced (version) diff --git a/specification/columns/commitmentdiscountid.md b/specification/columns/commitmentdiscountid.md index fd6a78bdf..30e99853f 100644 --- a/specification/columns/commitmentdiscountid.md +++ b/specification/columns/commitmentdiscountid.md @@ -1,8 +1,8 @@ # Commitment Discount ID -A Commitment Discount ID is the identifier assigned to a [*commitment-based discount*](#glossary:commitment-based-discount) by the provider. Commitment Discount ID is commonly used for scenarios like chargeback for *commitments* and savings per *commitment-based discount*. +A Commitment Discount ID is the identifier assigned to a [*commitment discount*](#glossary:commitment-discount) by the provider. Commitment Discount ID is commonly used for scenarios like chargeback for *commitments* and savings per *commitment discount*. -The CommitmentDiscountId column MUST be present in a FOCUS dataset when the provider supports *commitment-based discounts*. This column MUST be of type String and MUST NOT contain null values when a charge is related to a *commitment-based discount*. When a charge is not associated with a *commitment-based discount*, the column MUST be null. CommitmentDiscountId MUST be unique within the provider. +The CommitmentDiscountId column MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. This column MUST be of type String and MUST NOT contain null values when a charge is related to a *commitment discount*. When a charge is not associated with a *commitment discount*, the column MUST be null. CommitmentDiscountId MUST be unique within the provider. ## Column ID @@ -14,7 +14,7 @@ Commitment Discount ID ## Description -The identifier assigned to a *commitment-based discount* by the provider. +The identifier assigned to a *commitment discount* by the provider. ## Content constraints diff --git a/specification/columns/commitmentdiscountname.md b/specification/columns/commitmentdiscountname.md index 4ab4075ae..97abc352d 100644 --- a/specification/columns/commitmentdiscountname.md +++ b/specification/columns/commitmentdiscountname.md @@ -1,8 +1,8 @@ # Commitment Discount Name -A Commitment Discount Name is the display name assigned to a [*commitment-based discount*](#glossary:commitment-based-discount). +A Commitment Discount Name is the display name assigned to a [*commitment discount*](#glossary:commitment-discount). -The CommitmentDiscountName column MUST be present in a FOCUS dataset when the provider supports *commitment-based discounts*. This column MUST be of type String. The CommitmentDiscountName value MUST be null if the charge is not related to a *commitment-based discount* and MAY be null if a display name cannot be assigned to a *commitment-based discount*. CommitmentDiscountName MUST NOT be null if a display name can be assigned to a *commitment-based discount*. +The CommitmentDiscountName column MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. This column MUST be of type String. The CommitmentDiscountName value MUST be null if the charge is not related to a *commitment discount* and MAY be null if a display name cannot be assigned to a *commitment discount*. CommitmentDiscountName MUST NOT be null if a display name can be assigned to a *commitment discount*. ## Column ID @@ -14,7 +14,7 @@ Commitment Discount Name ## Description -The display name assigned to a *commitment-based discount*. +The display name assigned to a *commitment discount*. ## Content constraints diff --git a/specification/columns/commitmentdiscountstatus.md b/specification/columns/commitmentdiscountstatus.md index 085e4417e..8353d0284 100644 --- a/specification/columns/commitmentdiscountstatus.md +++ b/specification/columns/commitmentdiscountstatus.md @@ -1,8 +1,8 @@ # Commitment Discount Status -Commitment Discount Status indicates whether the charge corresponds with the consumption of the [*commitment-based discount*](#glossary:commitment-based-discount) identified in the CommitmentDiscountId column or the unused portion of the committed amount. +Commitment Discount Status indicates whether the charge corresponds with the consumption of the [*commitment discount*](#glossary:commitment-discount) identified in the CommitmentDiscountId column or the unused portion of the committed amount. -The CommitmentDiscountStatus column MUST be present in a FOCUS dataset when the provider supports *commitment-based discounts*. This column MUST be of type String, MUST be null when [CommitmentDiscountId](#commitmentdiscountid) is null, and MUST NOT be null when CommitmentDiscountId is not null and [Charge Category](#chargecategory) is "Usage". The CommitmentDiscountCategory MUST be one of the allowed values. +The CommitmentDiscountStatus column MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. This column MUST be of type String, MUST be null when [CommitmentDiscountId](#commitmentdiscountid) is null, and MUST NOT be null when CommitmentDiscountId is not null and [Charge Category](#chargecategory) is "Usage". The CommitmentDiscountCategory MUST be one of the allowed values. ## Column ID @@ -14,7 +14,7 @@ Commitment Discount Status ## Description -Indicates whether the charge corresponds with the consumption of a *commitment-based discount* or the unused portion of the committed amount. +Indicates whether the charge corresponds with the consumption of a *commitment discount* or the unused portion of the committed amount. ## Content constraints @@ -30,8 +30,8 @@ Allowed values: | Value | Description | | :----- | :-------------------------------------------------------------------------- | -| Used | Charges that utilized a specific amount of a commitment-based discount. | -| Unused | Charges that represent the unused portion of the commitment-based discount. | +| Used | Charges that utilized a specific amount of a commitment discount. | +| Unused | Charges that represent the unused portion of the commitment discount. | ## Introduced (version) diff --git a/specification/columns/commitmentdiscounttype.md b/specification/columns/commitmentdiscounttype.md index 71eb249c2..48e61926e 100644 --- a/specification/columns/commitmentdiscounttype.md +++ b/specification/columns/commitmentdiscounttype.md @@ -1,8 +1,8 @@ # Commitment Discount Type -Commitment Discount Type is a provider-assigned name to identify the type of [*commitment-based discount*](#glossary:commitment-based-discount) applied to the [*row*](#glossary:row). +Commitment Discount Type is a provider-assigned name to identify the type of [*commitment discount*](#glossary:commitment-discount) applied to the [*row*](#glossary:row). -The CommitmentDiscountType column MUST be present in a FOCUS dataset when the provider supports *commitment-based discounts*. This column MUST be of type String, MUST be null when [CommitmentDiscountId](#commitmentdiscountid) is null, and MUST NOT be null when CommitmentDiscountId is not null. +The CommitmentDiscountType column MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. This column MUST be of type String, MUST be null when [CommitmentDiscountId](#commitmentdiscountid) is null, and MUST NOT be null when CommitmentDiscountId is not null. ## Column ID @@ -14,7 +14,7 @@ Commitment Discount Type ## Description -A provider-assigned identifier for the type of *commitment-based discount* applied to the *row*. +A provider-assigned identifier for the type of *commitment discount* applied to the *row*. ## Content constraints diff --git a/specification/columns/contractedcost.md b/specification/columns/contractedcost.md index 37710d034..12912f761 100644 --- a/specification/columns/contractedcost.md +++ b/specification/columns/contractedcost.md @@ -2,7 +2,7 @@ Contracted Cost represents the cost calculated by multiplying [*contracted unit price*](#glossary:contracted-unit-price) and the corresponding [Pricing Quantity](#pricingquantity). Contracted Cost is denominated in the [Billing Currency](#billingcurrency) and is commonly used for calculating savings based on negotiation activities, by comparing it with [List Cost](#listcost). If negotiated discounts are not applicable, the Contracted Cost defaults to the List Cost. -**Important:** When aggregating Contracted Cost for savings calculations, it's important to exclude either one-time or recurring charges ([Charge Category](#chargecategory) "Purchase") that are paid to cover future eligible charges (e.g., [Commitment-Based Discount](#glossary:commitment-based-discount)) or the covered charges themselves. This exclusion helps prevent double counting of these charges in the aggregation. Which set of charges to exclude depends on whether cost are aggregated on a billed basis (exclude covered charges) or accrual basis (exclude Purchases for future charges). For instance, charges categorized as [Charge Category](#chargecategory) "Purchase" and their related [Charge Category](#chargecategory) "Tax" charges for a Commitment-Based Discount might be excluded from an accrual basis cost aggregation of Contracted Cost. This is because the "Usage" and "Tax" charge records provided during the term of the commitment discount already specify the Contracted Cost. Purchase charges that cover future eligible charges can be identified by filtering for [Charge Category](#chargecategory) "Purchase" records with a [Billed Cost](#billedcost) greater than 0 and an [Effective Cost](#effectivecost) equal to 0. +**Important:** When aggregating Contracted Cost for savings calculations, it's important to exclude either one-time or recurring charges ([Charge Category](#chargecategory) "Purchase") that are paid to cover future eligible charges (e.g., [Commitment Discount](#glossary:commitment-discount)) or the covered charges themselves. This exclusion helps prevent double counting of these charges in the aggregation. Which set of charges to exclude depends on whether cost are aggregated on a billed basis (exclude covered charges) or accrual basis (exclude Purchases for future charges). For instance, charges categorized as [Charge Category](#chargecategory) "Purchase" and their related [Charge Category](#chargecategory) "Tax" charges for a Commitment Discount might be excluded from an accrual basis cost aggregation of Contracted Cost. This is because the "Usage" and "Tax" charge records provided during the term of the commitment discount already specify the Contracted Cost. Purchase charges that cover future eligible charges can be identified by filtering for [Charge Category](#chargecategory) "Purchase" records with a [Billed Cost](#billedcost) greater than 0 and an [Effective Cost](#effectivecost) equal to 0. The ContractedCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. When [ContractedUnitPrice](#contractedunitprice) is present and not null, multiplying the ContractedUnitPrice by PricingQuantity MUST produce the ContractedCost, except in cases of [ChargeClass](#chargeclass) "Correction", which may address PricingQuantity or any cost discrepancies independently. diff --git a/specification/columns/contractedunitprice.md b/specification/columns/contractedunitprice.md index 0104c899a..faf177d32 100644 --- a/specification/columns/contractedunitprice.md +++ b/specification/columns/contractedunitprice.md @@ -1,6 +1,6 @@ # Contracted Unit Price -The Contracted Unit Price represents the agreed-upon unit price for a single [Pricing Unit](#pricingunit) of the associated SKU, inclusive of negotiated discounts, if present, while excluding negotiated commitment-based discounts or any other discounts. This price is denominated in the [Billing Currency](#billingcurrency). The Contracted Unit Price is commonly used for calculating savings based on negotiation activities. If negotiated discounts are not applicable, the Contracted Unit Price defaults to the [List Unit Price](#listunitprice). +The Contracted Unit Price represents the agreed-upon unit price for a single [Pricing Unit](#pricingunit) of the associated SKU, inclusive of negotiated discounts, if present, while excluding negotiated commitment discounts or any other discounts. This price is denominated in the [Billing Currency](#billingcurrency). The Contracted Unit Price is commonly used for calculating savings based on negotiation activities. If negotiated discounts are not applicable, the Contracted Unit Price defaults to the [List Unit Price](#listunitprice). The ContractedUnitPrice column MUST be present in a FOCUS dataset when the provider supports negotiated pricing concept. This column MUST be a Decimal within the range of non-negative decimal values, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When ContractedUnitPrice is present and not null, multiplying ContractedUnitPrice by [PricingQuantity](#pricingquantity) MUST equal [ContractedCost](#contractedcost), except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. @@ -14,7 +14,7 @@ Contracted Unit Price ## Description -The agreed-upon unit price for a single Pricing Unit of the associated SKU, inclusive of negotiated discounts, if present, while excluding negotiated commitment-based discounts or any other discounts. +The agreed-upon unit price for a single Pricing Unit of the associated SKU, inclusive of negotiated discounts, if present, while excluding negotiated commitment discounts or any other discounts. ## Content Constraints diff --git a/specification/columns/effectivecost.md b/specification/columns/effectivecost.md index 25c0f8ac7..eb5b28887 100644 --- a/specification/columns/effectivecost.md +++ b/specification/columns/effectivecost.md @@ -5,7 +5,7 @@ Effective Cost represents the [*amortized*](#glossary:amortization) cost of the This column resolves two challenges that are faced by practitioners: 1. Practitioners need to *amortize* relevant purchases, such as upfront fees, throughout the *commitment* and distribute them to the appropriate reporting groups (e.g. [*tags*](#glossary:tag), [*resources*](#glossary:resource)). -2. Many [*commitment-based discount*](#glossary:commitment-based-discount) constructs include a recurring expense for the *commitment* for every [*billing period*](#glossary:billing-period) and must distribute this cost to the *resources* using the *commitment*. This forces reconciliation between the initial *commitment* [*row*](#glossary:row) per period and the actual usage *rows*. +2. Many [*commitment discount*](#glossary:commitment-discount) constructs include a recurring expense for the *commitment* for every [*billing period*](#glossary:billing-period) and must distribute this cost to the *resources* using the *commitment*. This forces reconciliation between the initial *commitment* [*row*](#glossary:row) per period and the actual usage *rows*. The EffectiveCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. EffectiveCost MUST be 0 when ChargeCategory is "Purchase" and the purchase is intended to cover future eligible charges. The aggregated EffectiveCost for a billing period may not match the charge received on the invoice for the same *billing period*. diff --git a/specification/columns/listcost.md b/specification/columns/listcost.md index ad881ad3e..de5fabc87 100644 --- a/specification/columns/listcost.md +++ b/specification/columns/listcost.md @@ -2,7 +2,7 @@ List Cost represents the cost calculated by multiplying the [*list unit price*](#glossary:list-unit-price) and the corresponding [Pricing Quantity](#pricingquantity). List Cost is denominated in the [Billing Currency](#billingcurrency) and is commonly used for calculating savings based on various rate optimization activities, by comparing it with [Contracted Cost](#contractedcost), [Billed Cost](#billedcost) and [Effective Cost](#effectivecost). -**Important:** When aggregating List Cost for savings calculations, it's important to exclude either one-time or recurring charges ([Charge Category](#chargecategory) "Purchase") that are paid to cover future eligible charges (e.g., [Commitment-Based Discount](#glossary:commitment-based-discount)) or the covered charges themselves. This exclusion helps prevent double counting of these charges in the aggregation. Which set of charges to exclude depends on whether cost are aggregated on a billed basis (exclude covered charges) or accrual basis (exclude Purchases for future charges). For instance, charges categorized as [Charge Category](#chargecategory) "Purchase" and their related [Charge Category](#chargecategory) "Tax" charges for a Commitment-Based Discount might be excluded from an accrual basis cost aggregation of List Cost. This is because the "Usage" and "Tax" charge records provided during the term of the commitment discount already specify the List Cost. Purchase charges that cover future eligible charges can be identified by filtering for [Charge Category](#chargecategory) "Purchase" records with a [Billed Cost](#billedcost) greater than 0 and an [Effective Cost](#effectivecost) equal to 0. +**Important:** When aggregating List Cost for savings calculations, it's important to exclude either one-time or recurring charges ([Charge Category](#chargecategory) "Purchase") that are paid to cover future eligible charges (e.g., [Commitment Discount](#glossary:commitment-discount)) or the covered charges themselves. This exclusion helps prevent double counting of these charges in the aggregation. Which set of charges to exclude depends on whether cost are aggregated on a billed basis (exclude covered charges) or accrual basis (exclude Purchases for future charges). For instance, charges categorized as [Charge Category](#chargecategory) "Purchase" and their related [Charge Category](#chargecategory) "Tax" charges for a Commitment Discount might be excluded from an accrual basis cost aggregation of List Cost. This is because the "Usage" and "Tax" charge records provided during the term of the commitment discount already specify the List Cost. Purchase charges that cover future eligible charges can be identified by filtering for [Charge Category](#chargecategory) "Purchase" records with a [Billed Cost](#billedcost) greater than 0 and an [Effective Cost](#effectivecost) equal to 0. The ListCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. When [ListUnitPrice](#listunitprice) is present and not null, multiplying the ListUnitPrice by PricingQuantity MUST produce the ListCost, except in cases of [ChargeClass](#chargeclass) "Correction", which may address PricingQuantity or any cost discrepancies independently. diff --git a/specification/columns/pricingcategory.md b/specification/columns/pricingcategory.md index c9037ec43..7f881fa46 100644 --- a/specification/columns/pricingcategory.md +++ b/specification/columns/pricingcategory.md @@ -1,6 +1,6 @@ # Pricing Category -Pricing Category describes the pricing model used for a charge at the time of use or purchase. It can be useful for distinguishing between charges incurred at the [*list unit price*](#glossary:list-unit-price) or a reduced price and exposing optimization opportunities, like increasing [commitment-based discount](#glossary:commitment-based-discount) coverage. +Pricing Category describes the pricing model used for a charge at the time of use or purchase. It can be useful for distinguishing between charges incurred at the [*list unit price*](#glossary:list-unit-price) or a reduced price and exposing optimization opportunities, like increasing [commitment discount](#glossary:commitment-discount) coverage. The PricingCategory column adheres to the following requirements: @@ -38,9 +38,9 @@ Allowed values: | Value | Description | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Standard | Charges priced at the agreed upon rate for the billing account, including negotiated discounts. This includes any flat rate and volume/tiered pricing but does not include dynamic or commitment-based discount pricing. | +| Standard | Charges priced at the agreed upon rate for the billing account, including negotiated discounts. This includes any flat rate and volume/tiered pricing but does not include dynamic or commitment discount pricing. | | Dynamic | Charges priced at a variable rate determined by the provider. This includes any product or service with a unit price the provider can change without notice, like interruptible or low priority resources. | -| Committed | Charges with reduced prices due to a commitment-based discount specified by the Commitment Discount ID. | +| Committed | Charges with reduced prices due to a commitment discount specified by the Commitment Discount ID. | | Other | Charges priced in a way not covered by another pricing category. | ## Introduced (version) diff --git a/specification/glossary.md b/specification/glossary.md index 677b138d6..dae733a37 100644 --- a/specification/glossary.md +++ b/specification/glossary.md @@ -44,7 +44,7 @@ The time window for which a charge is effective, inclusive of the start date and A customer's agreement to consume a specific quantity of a service or resource over a defined period, usually also creating a financial commitment throughout the entirety of the commitment period. Some commitments also hold Providers to certain assurance levels of resource availability. -Commitment-Based Discount +Commitment Discount Also known as Commitment Discount, this is a commitment for an amount of usage or spend throughout a specified term, in exchange for discounted unit pricing on that amount. The commitment may be based on quantities of resource units or monetary value, with various payment options and time frames. diff --git a/specification/use_case_library.md b/specification/use_case_library.md index 535cb9ec5..b8b5da96c 100644 --- a/specification/use_case_library.md +++ b/specification/use_case_library.md @@ -5,7 +5,7 @@ The following table contains a set of commonly performed FinOps scenarios that w | Persona | Capability | Use Case | FOCUS Columns | |:--|:--|:--|:--| | Business / Product Owner | Budget Management | As a Business/Product Owner, I need to compare actual usage costs incurred within a time period to the amount forecasted. | BilledCost
BillingAccountId
BillingAccountName
ChargePeriodStart
ChargePeriodEnd
ChargeCategory
Provider | -| Engineering & Operations | Budget Management | As an Engineering Manager who wants to reduce their billed cost for Compute for a specific provider, I want to understand what is my current rate of Commitment based discount (without negotiated discounts) per type of commitment, so that I can strategize further purchases | BillingPeriodStart
CommitmentDiscountType
EffectiveCost
ProviderName
ServiceName
SubAccountId
SubAccountName | +| Engineering & Operations | Budget Management | As an Engineering Manager who wants to reduce their billed cost for Compute for a specific provider, I want to understand what is my current rate of commitment discount (without negotiated discounts) per type of commitment, so that I can strategize further purchases | BillingPeriodStart
CommitmentDiscountType
EffectiveCost
ProviderName
ServiceName
SubAccountId
SubAccountName | | Engineering & Operations | Data Analysis and Showback | As an Engineer, I want to understand the costs of the components that belong to an application | ChargeDescription
ChargePeriodStart
EffectiveCost
ResourceId
ResourceName
ResourceType
ServiceCategory
ServiceName
SkuId
Tags | | Engineering & Operations | Data Analysis and Showback | As an Engineer, I want to understand the costs of the components for a specific resource | ChargePeriodStart
EffectiveCost
ResourceId
ResourceName
SkuId | | Engineering & Operations | Data Analysis and Showback | As an Engineer, I want to understand the costs of all components and resources within a subaccount | ChargePeriodStart
EffectiveCost
ResourceId
ResourceName
SkuId
SubAccountId | @@ -16,7 +16,7 @@ The following table contains a set of commonly performed FinOps scenarios that w | Finance | Budget Management | As a person in Finance, I need to update cloud budget with actual cost details within a billing period | BilledCost
BillingPeriodStart
BillingPeriodEnd
ProviderName | | Finance | Budget Management | As a person in Finance, I need to update budget, by application, with actual cost details within a billed time period | BilledCost
BillingPeriodStart
BillingPeriodEnd
ProviderName
Tags | | Finance | Budget Management | As a person in Finance, I need to track tax costs month over month. | BillingPeriodStart
BilledCost
ChargeCategory
ProviderName | -| Finance | Budget Management | As a Financial Analyst or member of the company's treasury, I would like to understand what volume of commitment based charges are going to reoccur in the coming financial year | ChargeFrequency
BillingPeriodStart
BilledCost | +| Finance | Budget Management | As a Financial Analyst or member of the company's treasury, I would like to understand what volume of commitment discount charges are going to reoccur in the coming financial year | ChargeFrequency
BillingPeriodStart
BilledCost | | Finance | Data Analysis and Showback | As a Finance person of a company that sells SaaS services, I need to determine the resource quantity and type used by a customer so that a monthly invoice can be issued to the customer. | ProviderName
BillingPeriodStart
SkuId
PricingQuantity
ConsumedQuantity
ConsumedUnit
Tags | | Finance | Data Analysis and Showback | As a person in Finance, I need a report of all cost associated with a product from all geographic locations for a given month. | BilledCost
BillingCurrency
BillingAccountId
BillingAccountName
BillingPeriodEnd
ProviderName
Tags | | Finance | FinOps & Intersecting Frameworks | As a person in Finance, I need a report of service-level cost within a specific Sub Account as a part of a private pricing negotiation. | BillingPeriodStart
EffectiveCost
ProviderName
ServiceName
SubAccountId
SubAccountName | @@ -35,8 +35,8 @@ The following table contains a set of commonly performed FinOps scenarios that w | FinOps Practitioner | Managing Anomalies | As a FinOps Practitioner, I need to see the daily costs across all cloud providers, billing accounts, and sub accounts | BillingAccountId
SubAccountId
ChargePeriodStart
ChargePeriodEnd
ProviderName
EffectiveCost | | FinOps Practitioner | Managing Anomalies | As a FinOps Practitioner, I need to see the daily costs across all cloud providers, billing accounts, sub accounts, and region | BillingAccountId
SubAccountId
ChargePeriodStart
ChargePeriodEnd
EffectiveCost
ProviderName
RegionId
RegionName | | FinOps Practitioner | Managing Anomalies | As a FinOps practitioner, I need to see the daily costs across all cloud providers, billing accounts, sub accounts, and service | BillingAccountId
SubAccountId
ChargePeriodStart
ChargePeriodEnd
EffectiveCost
ProviderName
ServiceName | -| FinOps Practitioner | Managing Commitment Based Discounts | As a FinOps Practitioner, I want to track all commitment based discounts purchased for a time period | ProviderName
BillingAccountId
CommitmentDiscountId
CommitmentDiscountType
BilledCost
ChargePeriodStart
ChargeCategory | -| FinOps Practitioner | Managing Commitment Based Discounts | As a FinOps Practitioner, I want to track unused commitment charges in any given time period so that I consider them in my future commitment planning or remedy them | CommitmentDiscountStatus (filter)
CommitmentDiscountId
BilledCost
ChargePeriodStart | +| FinOps Practitioner | Managing Commitment Discounts | As a FinOps Practitioner, I want to track all commitment discounts purchased for a time period | ProviderName
BillingAccountId
CommitmentDiscountId
CommitmentDiscountType
BilledCost
ChargePeriodStart
ChargeCategory | +| FinOps Practitioner | Managing Commitment Discounts | As a FinOps Practitioner, I want to track unused commitment charges in any given time period so that I consider them in my future commitment planning or remedy them | CommitmentDiscountStatus (filter)
CommitmentDiscountId
BilledCost
ChargePeriodStart | | FinOps Practitioner | Resource Utilization & Efficiency | As a FinOps Practitioner, I need to analyze the fleet diversity in order to run a campaign to standardize application architecture. | ChargeCategory
ChargeDescription
ChargePeriodStart
ProviderName
ResourceType
SubAccountId
ServiceName | | FinOps Practitioner | Resource Utilization & Efficiency | As a FinOps Practitioner, I need to analyze the fleet diversity in order to run a campaign to standardize application architecture within a specific service | ChargeCategory
ChargeDescription
ChargePeriodStart
ProviderName
ResourceType
SubAccountId
ServiceName | | FinOps Practitioner | Resource Utilization & Efficiency | As a FinOps Practitioner, I need to identify total refunds within a billing period. | ProviderName
BillingAccountId
ServiceCategory
BilledCost
BillingPeriodStart
ChargeCategory
ChargeClass | diff --git a/supporting_content/attributes/discount_handling.md b/supporting_content/attributes/discount_handling.md index 4eac11eae..53eba39d4 100644 --- a/supporting_content/attributes/discount_handling.md +++ b/supporting_content/attributes/discount_handling.md @@ -49,14 +49,14 @@ Explanation of the unused commitment row: Providers offer various discounting schemes for their service offerings. These discounts typically fall into common types such as: -- Commitment-based discounts +- Commitment discounts - Tier-based discounts - Negotiated discounts - Promotional discounts - Usage-based discounts - Partner discounts -## Commitment-based discounts +## Commitment discounts - Usage-based commitment discounts - Spend-based commitment discounts diff --git a/supporting_content/columns/chargecategory.md b/supporting_content/columns/chargecategory.md index c4047d6d2..47a3df444 100644 --- a/supporting_content/columns/chargecategory.md +++ b/supporting_content/columns/chargecategory.md @@ -31,7 +31,7 @@ Current values observed in billing data for various scenarios: | GCP | adjustment | Adjustment | ![Screenshot of GCP cost details with type and mode columns.](https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/assets/399533/af90e4cd-f3c0-448a-bb0f-0249bcf7135c)
Example 1:
Description: "Billing correction - Adjustment for project X for incorrect Flexible CUD charge"
Mode: "MANUAL_ADJUSTMENT"
Type: "GENERAL_ADJUSTMENT" | | GCP | rounding_error | Adjustment | These show up as monthly rows without a project as a credit | | GCP | credit | Adjustment | Fields: type, name, amount, full_name, id
![Screenshot of a table with a type column and 5 rows of example values](https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/assets/399533/15bcc210-5a36-473b-aeac-c1d2682dfdc8) | -| Microsoft | Purchase | Purchase | Upfront or recurring fee for Marketplace offers or commitment-based discounts. | +| Microsoft | Purchase | Purchase | Upfront or recurring fee for Marketplace offers or commitment discounts. | | Microsoft | Usage | Usage | Consumption-based usage of deployed resources. | | Microsoft | Refund | Adjustment | Refund provided by support. | | Microsoft | Adjustment | Adjustment | Rounding errors. | diff --git a/supporting_content/columns/contractedunitprice.md b/supporting_content/columns/contractedunitprice.md index 9be525c3a..83c0764d2 100644 --- a/supporting_content/columns/contractedunitprice.md +++ b/supporting_content/columns/contractedunitprice.md @@ -50,7 +50,7 @@ Current column mappings found in available data sets: * [Azure Billing Enterprise APIs - PriceSheet | Microsoft Learn](https://learn.microsoft.com/en-us/rest/api/billing/enterprise/ provides information for EA. * TODO: Check if there is a Microsoft Custom Prices REST API, which might provide custom/negotiated prices for all account types. -* **unitPrice** (The price per unit for the charge.) includes commitment based discounts and thus is not applicable for all use cases. Furthermore, +* **unitPrice** (The price per unit for the charge.) includes commitment discounts and thus is not applicable for all use cases. Furthermore, * According to documentation, it is available only for EA and PAYG. * It is unclear if it's denominated in Billing or Pricing currency. Noticed that for different accounts types different relations apply * In one case `unitPrice * quantity = costInBillingCurrency` diff --git a/supporting_content/columns/listunitprice.md b/supporting_content/columns/listunitprice.md index b42175a7a..f9e069c4f 100644 --- a/supporting_content/columns/listunitprice.md +++ b/supporting_content/columns/listunitprice.md @@ -51,7 +51,7 @@ Current column mappings found in available data sets: ### Current data sources and SkuPriceId -* For GCP and OCI, Pricing Data serves as the sole data source for ListUnitPrice, while for AWS, it is the preferred data source due to concerns related to volume/tier-based pricing. To determine the relevant price in Pricing Data for a specific charge record, the billing data must include the SkuPriceId. * Considering that providers publish not only list/on-demand prices but also unit prices inclusive of commitment-based discounts (and perhaps more), we can't directly associate ListUnitPrice with the SkuPriceId. +* For GCP and OCI, Pricing Data serves as the sole data source for ListUnitPrice, while for AWS, it is the preferred data source due to concerns related to volume/tier-based pricing. To determine the relevant price in Pricing Data for a specific charge record, the billing data must include the SkuPriceId. * Considering that providers publish not only list/on-demand prices but also unit prices inclusive of commitment discounts (and perhaps more), we can't directly associate ListUnitPrice with the SkuPriceId. * How to resolve the ListUnitPrice from the Price Sheet or Pricing API based on SkuPriceId? Consider introducing an additional column that would contain the ID of the corresponding List/On-Demand SKU Price ID, instead of providing guidelines and expecting practitioners to resolve it. * As previously mentioned, when BillingCurrency and PricingCurrency differ, the exchange rate must also be considered. @@ -63,7 +63,7 @@ Current column mappings found in available data sets: * Is it ok to assume that rates of interruptible resources and services (spare capacity, spot) fall into category of dynamically priced SKU rates? (do we plan to cover this in the glossary?) * OPTION B: The List Unit Price represents a suggested provider-published unit price for a single [Pricing Unit](#pricingunit) of the associated SKU, exclusive of any discounts. * Is it ok to assume that practitioners perceive mentioned rates as reduced rates rather than discounts? - * OPTION C: The List Unit Price represents a suggested provider-published unit price for a single [Pricing Unit](#pricingunit) of the associated SKU, exclusive of any negotiated or commitment-based discounts. + * OPTION C: The List Unit Price represents a suggested provider-published unit price for a single [Pricing Unit](#pricingunit) of the associated SKU, exclusive of any negotiated or commitment discounts. * Is it ok to assume that those are the only two discounts? * Being inclusive of free-tier, volume/tier-based, BYOL-based and dynamically priced SKU rates, the List Unit Price cannot be used for calculating savings based on volume/tier-based pricing, the use of pre-owned software licenses (BYOL - Bring Your Own License), leveraging interruptible resources and/or services, or optimizing usage to take advantage of dynamic pricing models. diff --git a/supporting_content/columns/pricingcategory.md b/supporting_content/columns/pricingcategory.md index d899a6e07..e99146935 100644 --- a/supporting_content/columns/pricingcategory.md +++ b/supporting_content/columns/pricingcategory.md @@ -34,7 +34,7 @@ Current values observed in billing data for various scenarios: ## Discussion Topics * Goal of the column is to enable practitioners to identify charges that have reduced prices vs. not. - * The most common question for this column is to identify commitment-based discounts and spot separate from on-demand. + * The most common question for this column is to identify commitment discounts and spot separate from on-demand. * In 0.5, we didn't have enough time to close on how spot would be included: * Someone mentioned that "spot" was a marketing term, so we tried to avoid it. * We discussed values like "Preemptible" (confusing), "Interruptible" (not a pricing model), "Market-Based", "Variable", and "Dynamic". Ultimately, we agreed on "Dynamic". @@ -64,7 +64,7 @@ Current values observed in billing data for various scenarios: * We felt "Standard" was more clear as a differentiator from "Tiered" pricing. Another alternative was "Flat Rate". * We also discussed whether to use "Commitment-Based" or "Discounted". * If we use "Discounted", then any future discounting strategy could get rolled into a single column without the need to change values. - * The main downside of this is that, given how important commitment-based discounts are (and the fact that they are one of the primary reasons for adding this column), we felt it was important to call them out explicitly. + * The main downside of this is that, given how important commitment discounts are (and the fact that they are one of the primary reasons for adding this column), we felt it was important to call them out explicitly. * Additionally, given different discount strategies will price things differently, it's also important that we distinguish the separate pricing models at the top level. * We also didn't have any other clear examples that would fall into "Discounted" pricing that would be meaningfully grouped together in a way that practitioners would want to see together and not distinguished separately from their committed costs. * We also discussed the term "Dynamic" and whether it was clear enough. diff --git a/supporting_content/columns/pricingquantity.md b/supporting_content/columns/pricingquantity.md index ced9b2608..11598c403 100644 --- a/supporting_content/columns/pricingquantity.md +++ b/supporting_content/columns/pricingquantity.md @@ -9,7 +9,7 @@ Current column mappings found in available data sets: | AWS | Cost and Usage Report | lineItem/UsageAmount (NOTE: how to handle reservation/TotalReservedUnits| | GCP | BigQuery Billing Export | usage.amount_in_pricing_units (NOTE: usage.amount provides UsageQuantity) | | Microsoft | Cost Details | Not available (NOTE: While Quantity is the closest, it provides UsageQuantity and not PricingQuantity) | -| OCI | Cost and Usage Report | usage/billedQuantity Note: usage/billedQuantity preferred over usage/billedQuantityOverage since the latter does not include the quantity covered by Universal Credits (commitment-based discounts) | +| OCI | Cost and Usage Report | usage/billedQuantity Note: usage/billedQuantity preferred over usage/billedQuantityOverage since the latter does not include the quantity covered by Universal Credits (commitment discounts) | ## References and Resources From b9b8a24dac681acb9d4f8cab85cefd7afd93fb2c Mon Sep 17 00:00:00 2001 From: Joaquin Date: Tue, 3 Sep 2024 15:05:59 +0200 Subject: [PATCH 20/52] [ADMIN] Add editorial guidelines document (#501) This PR supersedes PR #499 --------- Co-authored-by: Karl <133434112+kk09v@users.noreply.github.com> Co-authored-by: Michael Flanakin --- EDITORIAL_GUIDELINES.md | 232 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) create mode 100644 EDITORIAL_GUIDELINES.md diff --git a/EDITORIAL_GUIDELINES.md b/EDITORIAL_GUIDELINES.md new file mode 100644 index 000000000..189a612da --- /dev/null +++ b/EDITORIAL_GUIDELINES.md @@ -0,0 +1,232 @@ +## Editorial Style Guidelines +The "Editorial Style Guidelines" section ensures consistency and clarity across all documentation. Adhering to these guidelines is crucial for maintaining a unified style, which enhances readability and reduces misinterpretation. By following the specified standards—whether in formatting, linking, or structuring information—we ensure that all documents are professional, clear, and aligned with our editorial principles. Consistent application of these guidelines contributes to high-quality, user-friendly documentation. + +These guidelines can be modified through a Pull Request (PR), which the members must review and agree upon. This process ensures that any changes are thoughtfully considered and maintains the overall integrity of our editorial standards. + + +
Date
v1.2Jun 20, 2025Mid, 2025 REQ 4: Keyword value/brief description
REQ 5: Keyword value/brief description
@@ -28,7 +28,7 @@ This section outlines the planned release schedule and key milestones for the FO
v1.3Nov 11, 2025Late, 2025 REQ 7: Keyword value/brief description
REQ 8: Keyword value/brief description
From 2bb60023557b872b6821223f72730ee3593bbabc Mon Sep 17 00:00:00 2001 From: Joaquin Date: Thu, 6 Jun 2024 21:18:10 -0700 Subject: [PATCH 07/52] =?UTF-8?q?Update=20scope=20and=20interim=20consiste?= =?UTF-8?q?ncy=20review=20milestones,=20and=20scope=20top=E2=80=A6=20(#478?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update RELEASE_PLANNING Content: * Change Jun 27 to Jul 18 as new milestone for approval v1.1 scope * Move interim Consistency Review to July 18 to Aug 1st * Add first Release v1.1 scope topic: Improve SKU Details" --- RELEASE-PLANNING.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/RELEASE-PLANNING.md b/RELEASE-PLANNING.md index e2586f614..f1b5a655d 100644 --- a/RELEASE-PLANNING.md +++ b/RELEASE-PLANNING.md @@ -12,7 +12,7 @@ This section outlines the planned release schedule and key milestones for the FO
v1.1 Nov 11, 2024 - REQ 1: Keyword value/brief description
+ REQ 1: Improve SKU Details
REQ 2: Keyword value/brief description
REQ 3: Keyword value/brief description
17 weeks to develop FOCUS Rel v1.1
27-Jun-2418-Jul-24 Approval FOCUS v1.1 Scope Close the scope for FOCUS Release v1.1
27-Jun-24 to 11-Jul-2418-Jul-24 to 1-Aug-24 Start / End Interim Consistency Review Two weeks Interim Consistency Review FOCUS Rel v1.1
v1.1 Nov 11, 2024 - REQ 1: Improve SKU Details
- REQ 2: Keyword value/brief description
- REQ 3: Keyword value/brief description + SKU and SKU Price Details +
    +
  • Provide deeper visibility into SKU and SKU Price details (in addition to the current SKU and SKU Price IDs that are available in FOCUS) which enables many standard FinOps use cases from cost reporting to commitment optimization. +
  • +
+ Deeper service classification +
    +
  • Move beyond the highest-level service categorization to a sub-categorization for services while adding flexibility for providers to share their native categorizations within FOCUS. +
  • +
+ Capacity Reservation +
    +
  • Ability to represent on-demand capacity reservations within FOCUS datasets. +
  • +
+ Improve metadata support +
    +
  • Strengthen the correlation between FOCUS-compatible datasets and the corresponding metadata to better support data analysis and ETL use cases +
  • +
18-Jul-24 to 1-Aug-24 Start / End Interim Consistency ReviewTwo weeks Interim Consistency Review FOCUS Rel v1.1CANCELED Two weeks Interim Consistency Review FOCUS Rel v1.1
19-Sep-24 to 03-Oct-24
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ComponentDisplay (PDF, HTML)Markdown (examples)Editorial Guidelines
Column & Attribute Names: + Column Names:
+ - Pricing Quantity
+ - Pricing Unit
+ - Provider

+ Attribute Names:
+ - Currency Code Format
+ - Date/Time Format +
+ Column Names:
+    **Pricing Quantity**
+    **Pricing Unit**
+    **Provider**

+ Attribute Names:
+    **Currency Code Format**
+    **Date/Time Format**
+
+ - Bold
+ - Use the display name in the non-normative section.
+ - The first occurrence in a section is linked to the section. +
Column & Attribute IDs: + Columns IDs:
+ - PricingQuantity
+ - PricingUnit
+ - ProviderName

+ Attributes IDs:
+ - CurrencyCodeFormat
+ - DateTimeFormat
+
+ Columns IDs::
+    PricingQuantity
+    PricingUnit
+    ProviderName

+ Attributes IDs:
+    CurrencyCodeFormat
+    DateTimeFormat
+
+ - Use PascalCamel case (the first letter of every word, is capitalized) + - Normal text without bold or italics.
+ - The first occurrence in a section is linked to the section. +
Normative Keywords & Statements + MUST, MAY, MUST NOT and normative statements + + This column:
+    * MUST NOT be null when ChargeClass is ...
+    * MUST be null when ChargeCategory is ...
+    * MAY be null for all other combinations of ...
+
+ - All uppercase, without bold.
+ - Bullet list format.
+
Glossary + SKU, resource, service + + [*SKU*](#glossary:sku)
+ [*resource*](#glossary:resource)
+ [*service*](#glossary:service)
+
+ - Blue font + italic
+ - The first occurrence in a section is linked to the glossary. +
Important Text image> Important Consideration- It is added as a note.
Key-Value FormatJSON Script +
+**Example**:
+```json
+{
+    "key1": "value1",
+    "key2": true,
+    "key3": 123
+}
+```
+            
+
- Monospace font
Tablesimageimage - Tables: Simple tables can be created using markdown, but for more complex tables, it is RECOMMENDED to use HTML elements. See the example below.
+ +**Editorial Notes** +* **Linking Only the First Time**: To prevent excessive linking within sections, Column Name, Column ID, Attributes Names, Attributes IDs, and Glossary will only be linked to their corresponding section or glossary the first time they appear in a section. + +* **Normative Requirements as a Bullet List**: Normative statements (those using Normative Keywords) should be written as bullet points instead of lengthy sentences. + +### Example + +> **2.28. Pricing Quantity** +> +> The **[Pricing Quantity](#pricing-quantity)** represents the volume of a given [SKU](#glossary:sku) associated with a [resource](#glossary:resource) or [service](#glossary:service) used or purchased, based on the **[Pricing Unit](#pricing-unit)**. Distinct from **[Consumed Quantity](#consumed-quantity)** (complementary to **[Consumed Unit](#consumed-unit)**), it focuses on pricing and cost, not resource and service consumption. +> +> * The PricingQuantity column MUST be present in the billing data. +> * This column MUST be of type Decimal and MUST conform to Numeric Format requirements. +> * The value MAY be negative in cases where ChargeClass is "Correction". +> +> This column: +> * MUST NOT be null when ChargeClass is not "Correction" and ChargeCategory is "Usage" or "Purchase", +> * MUST be null when ChargeCategory is "Tax", and +> * MAY be null for all other combinations of ChargeClass and ChargeCategory. +> * When unit prices are not null, multiplying PricingQuantity by a unit price MUST produce a result equal to the corresponding cost metric, except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. +> +> **2.28.1. Column ID** +> +> PricingQuantity +> +> **2.28.2. Display Name** +> +> Pricing Quantity +> +> **2.28.3. Description** +> +> The volume of a given SKU associated with a resource or service used or purchased, based on the Pricing Unit. +> +> **2.28.4. Content Constraints Constraint** +> +> image +> +> **2.28.5. Introduced (version)** +> +> 1.0-preview + +### Example HTML Table +This is an example of a complex table with merged rows and columns, along with an additional header row. + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Heading 1Heading 2Heading 3
Cell 1,1 and Cell 1,2 MergedCell 1,3Cell 1,4
Heading 4Heading 5Heading 6Heading 7
Cell 2,1 & Cell 2,2Cell 3,3
&
Cell 4,3
Cell 3,4
Cell 4,1Cell 4,2Cell 4,4
+ +This is how it is written in HTML: +```html + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Heading 1Heading 2Heading 3
Cell 1,1 and Cell 1,2 MergedCell 1,3Cell 1,4
Heading 4Heading 5Heading 6Heading 7
Cell 2,1 & Cell 2,2Cell 3,3
&
Cell 4,3
Cell 3,4
Cell 4,1Cell 4,2Cell 4,4
+ +``` From 7091e62b133242b7f36a97b82de9dcec9073e557 Mon Sep 17 00:00:00 2001 From: Karl <133434112+kk09v@users.noreply.github.com> Date: Thu, 5 Sep 2024 17:11:51 -0500 Subject: [PATCH 21/52] #503a - Update SkuPriceId per SkuPriceDetails (#530) This change is dependent on #503 being merged as it links to SkuPriceDetails. This change to SkuPriceId solves for a case where a provider does not have a SkuPriceId but wants to include SkuPriceDetails. This case was introduced when there was a change in scope of #503 to not include SkuDetails. Changes: - Reformatted normative to bullets - Added option (MAY) to repeat SkuId as SkuPriceId when there is no SkuPriceId, as long as other conditions are not violated. --------- Co-authored-by: Udam Dewaraja Co-authored-by: Joaquin --- specification/columns/skupriceid.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/specification/columns/skupriceid.md b/specification/columns/skupriceid.md index 2dad50bc1..54bf2f977 100644 --- a/specification/columns/skupriceid.md +++ b/specification/columns/skupriceid.md @@ -2,7 +2,13 @@ A SKU Price ID is a unique identifier that defines the unit price used to calculate the charge. SKU Price ID can be referenced on a [*price list*](#glossary:price-list) published by a provider to look up detailed information, including a corresponding list unit price. The composition of the properties associated with the SKU Price ID may differ across providers. SKU Price ID is commonly used for analyzing cost based on pricing properties such as Terms and Tiers. -The SkuPriceId column MUST be present in a FOCUS dataset when the provider publishes a SKU price list. This column MUST be of type String. SkuPriceId MUST define a single unit price used for calculating the charge. The [ListUnitPrice](#listunitprice) MUST be associated with the SkuPriceId in the provider published *price list*. This column MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. A given value of SkuPriceId MUST be associated with one and only one [SkuId](#skuid), except in cases of commitment discount flexibility. +The *SkuPriceId* column adheres to the following requirements: +- *SkuPriceId* MUST be present in a FOCUS dataset when the provider publishes a SKU price list and MUST be of type String. +- *SkuPriceId* MUST define a single unit price used for calculating the charge. +- [*ListUnitPrice*](#listunitprice) MUST be associated with the *SkuPriceId* in the provider published price list. +- *SkuPriceId* MUST NOT be null when [*ChargeClass*](#chargeclass) is not "Correction" and [*ChargeCategory*](#chargecategory) is "Usage" or "Purchase", MUST be null when *ChargeCategory* is "Tax", and MAY be null for all other combinations of *ChargeClass* and *ChargeCategory*. +- A given value of *SkuPriceId* MUST be associated with one and only one [*SkuId*](#skuid), except in cases of commitment discount flexibility. +- If a provider does not have a *SkuPriceId* and wants to include information in columns linked to *SkuPriceId* such as *ListUnitPrice* or [*SkuPriceDetails*](#skupricedetails), the *SkuId* MAY be used in the *SkuPriceId* column as long as it adheres to the above conditions. ## Column ID From 4467a231afce6d9489d151415567bfcd2db706d3 Mon Sep 17 00:00:00 2001 From: gparker-at-sf <144709506+gparker-at-sf@users.noreply.github.com> Date: Thu, 5 Sep 2024 18:17:45 -0400 Subject: [PATCH 22/52] Capacity Reservation Proposal for ID & Status (#523) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Proposal based on Action Items, TF-3, Aug 16: [TF3-[#397](https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/issues/397)] George will draft a PR for the new “ID” and “Status” columns related to ODCRs. [TF3-[#397](https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/issues/397)] to consult AWS for further guidance on the feasibility of providing a CR ID in the billing data. --------- Co-authored-by: Christopher Harris Co-authored-by: Alex Hullah Co-authored-by: Udam Dewaraja Co-authored-by: Irena Jurica Co-authored-by: Michael Flanakin Co-authored-by: Joaquin --- .../columns/capacityreservationid.md | 37 ++++++++++++++++ .../columns/capacityreservationstatus.md | 43 +++++++++++++++++++ specification/glossary.md | 6 ++- 3 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 specification/columns/capacityreservationid.md create mode 100644 specification/columns/capacityreservationstatus.md diff --git a/specification/columns/capacityreservationid.md b/specification/columns/capacityreservationid.md new file mode 100644 index 000000000..ddc836936 --- /dev/null +++ b/specification/columns/capacityreservationid.md @@ -0,0 +1,37 @@ +# Capacity Reservation ID + +A Capacity Reservation ID is the identifier assigned to a [*capacity reservation*](#glossary:capacity-reservation) by the provider. Capacity Reservation ID is commonly used for scenarios to allocate charges for capacity reservation usage. + +The CapacityReservationId column adheres to the following requirements: + +* CapacityReservationId MUST be present in the billing data when the provider supports *capacity reservations* and MUST be of type String. +* CapacityReservationId SHOULD NOT be null when a charge is related to a capacity reservation. +* CapacityReservationId MUST NOT be null when a charge represents the unused portion of a *capacity reservation*. +* CapacityReservationId MUST be null when a charge is not related to a *capacity reservation*. +* CapacityReservationId MUST ensure global uniqueness within the provider and SHOULD be a fully-qualified identifier. + +## Column ID + +CapacityReservationId + +## Display Name + +Capacity Reservation ID + +## Description + +The identifier assigned to a *capacity reservation* by the provider. + +## Content constraints + +| Constraint | Value | +|:----------------|:-----------------| +| Column type | Dimension | +| Feature level | Conditional | +| Allows nulls | True | +| Data type | String | +| Value format | \ | + +## Introduced (version) + +1.1 diff --git a/specification/columns/capacityreservationstatus.md b/specification/columns/capacityreservationstatus.md new file mode 100644 index 000000000..448275909 --- /dev/null +++ b/specification/columns/capacityreservationstatus.md @@ -0,0 +1,43 @@ +# Capacity Reservation Status + +Capacity Reservation Status indicates whether the charge represents either the consumption of the [*capacity reservation*](#glossary:capacity-reservation) identified in the CapacityReservationId column or when the *capacity reservation* is unused. + +The CapacityReservationStatus column adheres to the following requirements: + * CapacityReservationStatus MUST be present in a FOCUS dataset when the provider supports *capacity reservations* and MUST be of type String. + * CapacityReservationStatus MUST be null when CapacityReservationId is null. + * CapacityReservationStatus MUST NOT be null when CapacityReservationId is not null and [ChargeCategory](#chargecategory) is "Usage". + * CapacityReservationStatus MUST be one of the allowed values. + * CapacityReservationStatus MUST label all unused *capacity reservation* charges and MUST label used *capacity reservation* charges if the provider supports it. + +## Column ID + +CapacityReservationStatus + +## Display Name + +Capacity Reservation Status + +## Description + +Indicates whether the charge represents either the consumption of a *capacity reservation* or when a *capacity reservation* is unused. + +## Content constraints + +| Constraint | Value | +| :-------------- | :------------- | +| Column type | Dimension | +| Feature level | Conditional | +| Allows nulls | True | +| Data type | String | +| Value format | Allowed Values | + +Allowed values: + +| Value | Description | +| :----- | :-------------------------------------------------------------------------- | +| Used | Charges that utilized a specific amount of a capacity reservation. | +| Unused | Charges that represent the unused portion of a capacity reservation. | + +## Introduced (version) + +1.1 diff --git a/specification/glossary.md b/specification/glossary.md index dae733a37..605ef15be 100644 --- a/specification/glossary.md +++ b/specification/glossary.md @@ -30,7 +30,11 @@ The time window that an organization receives an invoice for, inclusive of the s Block Pricing - A pricing approach where the cost of a particular resource or service is determined based on predefined quantities or tiers of usage. In these scenarios, the Pricing Unit and the corresponding Pricing Quantity can be different from the Consumed Unit and Consumed Quantity. +A pricing approach where the cost of a particular resource or service is determined based on predefined quantities or tiers of usage. In these scenarios, the Pricing Unit and the corresponding Pricing Quantity can be different from the Consumed Unit and Consumed Quantity. + +Capacity Reservation + +A capacity reservation is an agreement that secures a dedicated amount of resources or services for a specified period. This ensures the reserved capacity is always available and accessible, even if it's not fully utilized. Customers are typically charged for the reserved capacity, regardless of actual consumption. Charge From 31803cb0eecaa8edf6c08df41df34738d3160517 Mon Sep 17 00:00:00 2001 From: Karl <133434112+kk09v@users.noreply.github.com> Date: Thu, 5 Sep 2024 17:21:15 -0500 Subject: [PATCH 23/52] FOCUS #497: SkuPriceDetails column (#503) Introduction of _KeyValueFormat_ columns _SkuDetails_ and _SkuPriceDetails_ to capture properties of a **SKU ID** and **SKU Price ID**, respectively. **Lead Maintainer**: Karl ### Documents: * [#497](https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/issues/497) SKU Price Details (Issue) * Folder: [#497-srv-SKU-details-SKU-price-details](https://drive.google.com/drive/folders/1kbNNasX0xZBbLrcs1MQK5s5zWyv9o8CD?usp=drive_link) * PR [#503](https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/pull/503) SKU Details + SKU PriceDetails Columns by [karl.kraft@walmart.com](mailto:karl.kraft@walmart.com) * PR [#530](https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/pull/530) #503a - Update SkuPriceId per SkuPriceDetails by [karl.kraft@walmart.com](mailto:karl.kraft@walmart.com) * Spreadsheet:[ 24.07.17-AzureEA-FOCUS-and-PriceList-sample-dataset](https://docs.google.com/spreadsheets/d/1qoy5OjFeZFIK5fuVUKGiI_yCfN5_9tBxVBaRVlBgXtA/edit?gid=240278343#gid=240278343) * Document from Joseph:[ SKU Details from Providers](https://docs.google.com/document/d/1zPEUZ5L5wf9YAJ63ymW3tyrOFx-krJBB6sf1bHU_oOs/edit#heading=h.p2oplf92wckb) --------- Co-authored-by: Joaquin Co-authored-by: Michael Flanakin Co-authored-by: Joaquin Co-authored-by: Udam Dewaraja Co-authored-by: Irena Jurica --- .../attributes/column_naming_and_ordering.md | 2 +- specification/columns/columns.mdpp | 1 + specification/columns/skupricedetails.md | 57 +++++++++++++++++++ specification/glossary.md | 4 ++ 4 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 specification/columns/skupricedetails.md diff --git a/specification/attributes/column_naming_and_ordering.md b/specification/attributes/column_naming_and_ordering.md index 1b279efb1..d21360e03 100644 --- a/specification/attributes/column_naming_and_ordering.md +++ b/specification/attributes/column_naming_and_ordering.md @@ -21,7 +21,7 @@ Naming and ordering convention for columns appearing in a FOCUS dataset. ### Column Names * All columns defined by FOCUS MUST follow the following rules: - * Column IDs MUST use [Pascal case](https://techterms.com/definition/pascalcase). + * Column IDs MUST use [Pascal case](#glossary:pascalcase). * Column IDs MUST NOT use abbreviations. * Column IDs MUST be alphanumeric with no special characters. * Columns that have an ID and a Name MUST have the `Id` or `Name` suffix in the Column ID. Display Name for a Column MAY avoid the Name suffix if there are no other columns with the same name prefix. diff --git a/specification/columns/columns.mdpp b/specification/columns/columns.mdpp index f1d027b95..ef4f1ab0c 100644 --- a/specification/columns/columns.mdpp +++ b/specification/columns/columns.mdpp @@ -41,6 +41,7 @@ The FOCUS specification defines a group of columns that provide qualitative valu !INCLUDE "servicecategory.md",1 !INCLUDE "servicename.md",1 !INCLUDE "skuid.md",1 +!INCLUDE "skupricedetails.md",1 !INCLUDE "skupriceid.md",1 !INCLUDE "subaccountid.md",1 !INCLUDE "subaccountname.md",1 diff --git a/specification/columns/skupricedetails.md b/specification/columns/skupricedetails.md new file mode 100644 index 000000000..e64ea5405 --- /dev/null +++ b/specification/columns/skupricedetails.md @@ -0,0 +1,57 @@ +# SKU Price Details + +The **SKU Price Details** column represents a list of relevant properties shared by all charges with the same [**SKU Price ID**](#skupriceid). These properties provide qualitative and quantitative details about the service represented by a **SKU Price ID**. This can enable practitioners to calculate metrics such as total units of a service when it is not directly billed in those units (e.g. cores) and thus enables FinOps capabilities such as unit economics. These properties can also help a practitioner understand the specifics of a **SKU Price ID** and differentiate it other **SKU Price IDs**. + + +The *SkuPriceDetails* column adheres to the following requirements: + +- The *SkuPriceDetails* column MUST be in [*KeyValueFormat*](#key-valueformat). +- The key for a property SHOULD be formatted in [PascalCase](#glossary:pascalcase). +- The properties (both keys and values) contained in the *SkuPriceDetails* column MUST be shared across all charges having the same *SkuPriceId*, subject to the below provisions. + - Additional properties (key-value pairs) MAY be added to *SkuPriceDetails* going forward for a given *SkuPriceId*. + - Properties SHOULD NOT be removed from *SkuPriceDetails* for a given *SkuPriceId*, once they have been included. + - Individual properties (key-value pairs) SHOULD NOT be modified for a given *SkuPriceId* and SHOULD remain consistent over time. +- The key for a property SHOULD remain consistent across comparable SKUs having that property and the values for this key SHOULD remain in a consistent format. +- The *SkuPriceDetails* column MUST NOT contain properties which are not applicable to the corresponding *SkuPriceId*. +- The *SkuPriceDetails* column MAY contain properties which are already captured in other dedicated columns. +- If a property has a numeric value, it MUST represent the value for a single [*PricingUnit*](#pricingunit). +- The *SkuPriceDetails* column MUST be present in the billing data when the provider includes a *SkuPriceId*. + - The *SkuPriceDetails* column MAY be null when *SkuPriceId* is not null. + - The *SkuPriceDetails* column MUST be null when *SkuPriceId* is null. + +## Examples + +```json +{ + "OperationClass": "A", + "PricingTier": 2, + "CoreHours": 4, + "PreimumProcessing": true, +} +``` + +## Column ID + +SkuPriceDetails + +## Display Name + +SKU Price Details + +## Description + +A set of properties of a **SKU Price ID** which are meaningful and common to all instances of that **SKU Price ID**. + +## Content Constraints + +| Constraint | Value | +|:----------------|:-----------------| +| Column type | Dimension | +| Feature level | Conditional | +| Allows nulls | True | +| Data type | JSON | +| Value format | [Key-Value Format](#key-valueformat) | + +## Introduced (version) + +1.1 diff --git a/specification/glossary.md b/specification/glossary.md index 605ef15be..5ccf2cb4c 100644 --- a/specification/glossary.md +++ b/specification/glossary.md @@ -108,6 +108,10 @@ A company or organization that provides outsourced management and support of a r A term that describes a service that is available and provided immediately or as needed, without requiring a pre-scheduled appointment or prior arrangement. In cloud computing, virtual machines can be created and terminated as needed, i.e. on demand. +Pascal Case + +Pascal Case (PascalCase, also known as UpperCamelCase) is a format for identifiers which contain one or more words meaning the words are concatenated together with no delimiter and the first letter of each word is capitalized. + Practitioner An individual who performs FinOps within an organization to maximize the business value of using cloud and cloud-like services. From d6dc4dc82d854fc3cb6461dc7e7738e3091e97a8 Mon Sep 17 00:00:00 2001 From: Christopher Harris Date: Thu, 12 Sep 2024 07:53:32 -0400 Subject: [PATCH 24/52] Fix capacityreservation*, sku* build issues (#539) No change to content, just makes the `working_draft` branch pass builds 1. Adds `capacityreservation{id,status}` columns to `columns.mdpp` file. 2. Adds linter correction across all capacityreservation*, sku* columns: - `-` --> `*` bullets - spaces around lists --- .../columns/capacityreservationstatus.md | 11 ++++---- specification/columns/columns.mdpp | 2 ++ specification/columns/skupricedetails.md | 27 +++++++++---------- specification/columns/skupriceid.md | 13 ++++----- 4 files changed, 28 insertions(+), 25 deletions(-) diff --git a/specification/columns/capacityreservationstatus.md b/specification/columns/capacityreservationstatus.md index 448275909..24b449c29 100644 --- a/specification/columns/capacityreservationstatus.md +++ b/specification/columns/capacityreservationstatus.md @@ -3,11 +3,12 @@ Capacity Reservation Status indicates whether the charge represents either the consumption of the [*capacity reservation*](#glossary:capacity-reservation) identified in the CapacityReservationId column or when the *capacity reservation* is unused. The CapacityReservationStatus column adheres to the following requirements: - * CapacityReservationStatus MUST be present in a FOCUS dataset when the provider supports *capacity reservations* and MUST be of type String. - * CapacityReservationStatus MUST be null when CapacityReservationId is null. - * CapacityReservationStatus MUST NOT be null when CapacityReservationId is not null and [ChargeCategory](#chargecategory) is "Usage". - * CapacityReservationStatus MUST be one of the allowed values. - * CapacityReservationStatus MUST label all unused *capacity reservation* charges and MUST label used *capacity reservation* charges if the provider supports it. + +* CapacityReservationStatus MUST be present in a FOCUS dataset when the provider supports *capacity reservations* and MUST be of type String. +* CapacityReservationStatus MUST be null when CapacityReservationId is null. +* CapacityReservationStatus MUST NOT be null when CapacityReservationId is not null and [ChargeCategory](#chargecategory) is "Usage". +* CapacityReservationStatus MUST be one of the allowed values. +* CapacityReservationStatus MUST label all unused *capacity reservation* charges and MUST label used *capacity reservation* charges if the provider supports it. ## Column ID diff --git a/specification/columns/columns.mdpp b/specification/columns/columns.mdpp index ef4f1ab0c..42fca6745 100644 --- a/specification/columns/columns.mdpp +++ b/specification/columns/columns.mdpp @@ -9,6 +9,8 @@ The FOCUS specification defines a group of columns that provide qualitative valu !INCLUDE "billingcurrency.md",1 !INCLUDE "billingperiodend.md",1 !INCLUDE "billingperiodstart.md",1 +!INCLUDE "capacityreservationid.md",1 +!INCLUDE "capacityreservationstatus.md",1 !INCLUDE "chargecategory.md",1 !INCLUDE "chargeclass.md",1 !INCLUDE "chargedescription.md",1 diff --git a/specification/columns/skupricedetails.md b/specification/columns/skupricedetails.md index e64ea5405..fc4cb984e 100644 --- a/specification/columns/skupricedetails.md +++ b/specification/columns/skupricedetails.md @@ -2,22 +2,21 @@ The **SKU Price Details** column represents a list of relevant properties shared by all charges with the same [**SKU Price ID**](#skupriceid). These properties provide qualitative and quantitative details about the service represented by a **SKU Price ID**. This can enable practitioners to calculate metrics such as total units of a service when it is not directly billed in those units (e.g. cores) and thus enables FinOps capabilities such as unit economics. These properties can also help a practitioner understand the specifics of a **SKU Price ID** and differentiate it other **SKU Price IDs**. - The *SkuPriceDetails* column adheres to the following requirements: -- The *SkuPriceDetails* column MUST be in [*KeyValueFormat*](#key-valueformat). -- The key for a property SHOULD be formatted in [PascalCase](#glossary:pascalcase). -- The properties (both keys and values) contained in the *SkuPriceDetails* column MUST be shared across all charges having the same *SkuPriceId*, subject to the below provisions. - - Additional properties (key-value pairs) MAY be added to *SkuPriceDetails* going forward for a given *SkuPriceId*. - - Properties SHOULD NOT be removed from *SkuPriceDetails* for a given *SkuPriceId*, once they have been included. - - Individual properties (key-value pairs) SHOULD NOT be modified for a given *SkuPriceId* and SHOULD remain consistent over time. -- The key for a property SHOULD remain consistent across comparable SKUs having that property and the values for this key SHOULD remain in a consistent format. -- The *SkuPriceDetails* column MUST NOT contain properties which are not applicable to the corresponding *SkuPriceId*. -- The *SkuPriceDetails* column MAY contain properties which are already captured in other dedicated columns. -- If a property has a numeric value, it MUST represent the value for a single [*PricingUnit*](#pricingunit). -- The *SkuPriceDetails* column MUST be present in the billing data when the provider includes a *SkuPriceId*. - - The *SkuPriceDetails* column MAY be null when *SkuPriceId* is not null. - - The *SkuPriceDetails* column MUST be null when *SkuPriceId* is null. +* The *SkuPriceDetails* column MUST be in [*KeyValueFormat*](#key-valueformat). +* The key for a property SHOULD be formatted in [PascalCase](#glossary:pascalcase). +* The properties (both keys and values) contained in the *SkuPriceDetails* column MUST be shared across all charges having the same *SkuPriceId*, subject to the below provisions. + * Additional properties (key-value pairs) MAY be added to *SkuPriceDetails* going forward for a given *SkuPriceId*. + * Properties SHOULD NOT be removed from *SkuPriceDetails* for a given *SkuPriceId*, once they have been included. + * Individual properties (key-value pairs) SHOULD NOT be modified for a given *SkuPriceId* and SHOULD remain consistent over time. +* The key for a property SHOULD remain consistent across comparable SKUs having that property and the values for this key SHOULD remain in a consistent format. +* The *SkuPriceDetails* column MUST NOT contain properties which are not applicable to the corresponding *SkuPriceId*. +* The *SkuPriceDetails* column MAY contain properties which are already captured in other dedicated columns. +* If a property has a numeric value, it MUST represent the value for a single [*PricingUnit*](#pricingunit). +* The *SkuPriceDetails* column MUST be present in the billing data when the provider includes a *SkuPriceId*. + * The *SkuPriceDetails* column MAY be null when *SkuPriceId* is not null. + * The *SkuPriceDetails* column MUST be null when *SkuPriceId* is null. ## Examples diff --git a/specification/columns/skupriceid.md b/specification/columns/skupriceid.md index 54bf2f977..66206fef7 100644 --- a/specification/columns/skupriceid.md +++ b/specification/columns/skupriceid.md @@ -3,12 +3,13 @@ A SKU Price ID is a unique identifier that defines the unit price used to calculate the charge. SKU Price ID can be referenced on a [*price list*](#glossary:price-list) published by a provider to look up detailed information, including a corresponding list unit price. The composition of the properties associated with the SKU Price ID may differ across providers. SKU Price ID is commonly used for analyzing cost based on pricing properties such as Terms and Tiers. The *SkuPriceId* column adheres to the following requirements: -- *SkuPriceId* MUST be present in a FOCUS dataset when the provider publishes a SKU price list and MUST be of type String. -- *SkuPriceId* MUST define a single unit price used for calculating the charge. -- [*ListUnitPrice*](#listunitprice) MUST be associated with the *SkuPriceId* in the provider published price list. -- *SkuPriceId* MUST NOT be null when [*ChargeClass*](#chargeclass) is not "Correction" and [*ChargeCategory*](#chargecategory) is "Usage" or "Purchase", MUST be null when *ChargeCategory* is "Tax", and MAY be null for all other combinations of *ChargeClass* and *ChargeCategory*. -- A given value of *SkuPriceId* MUST be associated with one and only one [*SkuId*](#skuid), except in cases of commitment discount flexibility. -- If a provider does not have a *SkuPriceId* and wants to include information in columns linked to *SkuPriceId* such as *ListUnitPrice* or [*SkuPriceDetails*](#skupricedetails), the *SkuId* MAY be used in the *SkuPriceId* column as long as it adheres to the above conditions. + +* *SkuPriceId* MUST be present in a FOCUS dataset when the provider publishes a SKU price list and MUST be of type String. +* *SkuPriceId* MUST define a single unit price used for calculating the charge. +* [*ListUnitPrice*](#listunitprice) MUST be associated with the *SkuPriceId* in the provider published price list. +* *SkuPriceId* MUST NOT be null when [*ChargeClass*](#chargeclass) is not "Correction" and [*ChargeCategory*](#chargecategory) is "Usage" or "Purchase", MUST be null when *ChargeCategory* is "Tax", and MAY be null for all other combinations of *ChargeClass* and *ChargeCategory*. +* A given value of *SkuPriceId* MUST be associated with one and only one [*SkuId*](#skuid), except in cases of commitment discount flexibility. +* If a provider does not have a *SkuPriceId* and wants to include information in columns linked to *SkuPriceId* such as *ListUnitPrice* or [*SkuPriceDetails*](#skupricedetails), the *SkuId* MAY be used in the *SkuPriceId* column as long as it adheres to the above conditions. ## Column ID From 285dabe7707f448e70b7ee03c445bd83372d9cea Mon Sep 17 00:00:00 2001 From: Christopher Harris Date: Thu, 12 Sep 2024 16:36:52 -0400 Subject: [PATCH 25/52] FOCUS #319: Track (sometimes differing) commitment burndown units separately from consumed quantity/unit columns (#400) **Lead Maintainers**: Chris Harris, @cnharris10, Irena Jurica, @ijurica ### Documents: * **PR**: [#400](https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/pull/400) Commitment Utilization and Normalization * **PR**: [#524](https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/pull/524) rename Commitment-Based Discount to Commitment-Discount by [christopher.harris@datadoghq.com](mailto:christopher.harris@datadoghq.com) * [Usage vs Pricing Quantity and unit examples](https://docs.google.com/spreadsheets/d/1zA0brhrEntfWlzt5VNcNLBFnKPEiarajTF84o4ATeEw/edit?gid=1705742856#gid=1705742856) * [24.07.21-CommitmentUtilization-sample-datasets](https://docs.google.com/spreadsheets/d/1AYDPZ4rl90PPEbyQJUaGCUSwZ4s_sfy-8sO2KyNq0aM/edit?usp=drive_link) * [#400-commitment-utilization](https://drive.google.com/drive/u/0/folders/1u4_rc6TAqgMwuIQEKUVIX3zAzyvLM7Dj) folder * Document: [24.09.08 - Commitment utilization discussion](https://docs.google.com/document/d/1bOD6MYoFi0fX-MgLyN-hxUpNOSfojlsL0MSt3menOxk/edit?usp=sharing) * **Slack channel**: [#tf-commitment-utilization](https://f2-focus.slack.com/archives/C07CPAQDN75) * Approval deadline: ~Aug 29~, Sep 5 # Related PR's (Appendices): - https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/pull/528 - https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/pull/535 # Key Points - Adds 3 new columns to track CSP usage-based and spend-based commitments: `CommitmentDiscountConsumedQuantity`, `CommitmentDiscountPurchasedQuantity`, `CommitmentDiscountUnit` - `CommitmentDiscountConsumedQuantity` captures the commitment units used or unused in a charge period. - `CommitmentDiscountPurchasedQuantity` captures the commitment units purchased for one-time and recurring charge periods. - `CommitmentDiscountUnit` captures the unit that the commitment discount specifies. - Fixes a 1.0 bug by specifying that `ConsumedQuantity` and `ConsumedUnit` MUST be NULL for unused commitment rows. (reference [pr](https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/pull/507)) - Further scopes the definition of `commitment discount` and `negotiated discount` within the glossary and specifies that `CommitmentDiscount*` columns only correspond to `commitment discounts`. ## UPDATE (8/16/24) 1. Columns renamed to: `CommitmentDiscountConsumedQuantity`, `CommitmentDiscountUnit`, `CommitmentDiscountPurchaseQuantity` 2. `{List,Contracted}UnitPrice`, `Pricing{Quantity,Unit}` are null when `CommitmentDiscountStatus:Unused` 3. `{List,Contracted}Cost` are 0 when `CommitmentDiscountStatus:Unused` 4. New, official glossary terms incorporated from FinOps page for [`commitment-based discount`](https://www.finops.org/assets/terminology/#commitment-discounts) and [`negotiated discount`](https://www.finops.org/assets/terminology/#cloud-cost-management-terminology) ## UPDATE (8/19/24) 1. `{List,Contracted}{Cost,UnitPrice}` and `Pricing{Quantity,Unit}` columns now `0` or `null` when `CommitmentDiscountStatus:Unused` (TO BE DISCUSSED in TF-1) 2. `{List,Contracted}{Cost,UnitPrice}` and `Pricing{Quantity,Unit}` columns now in bullet-list format. 3. Correction-based normative text added by Irena. 4. This [pr](https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/pull/524) exists to renaming all instances of `/commitment[\-,\s]?based\sdiscount/i` to `commitment discount` (with correct casing) ### Discussion Points (8/20/24) 1. 2 current views for columns: `{List,Contracted}{Cost,UnitPrice}` and `Pricing{Quantity,Unit}` when `CommitmentDiscountStatus:Unused` a. Set all values to appropriate `null` or `0` values (current). b. Set all values to the same values as the purchase record (if it exists). 2. Currently, `PricingCategory MUST be "Committed" when [CommitmentDiscountId](#commitmentdiscountid) is not null`. Should this be changed to `Standard` for `Purchase` rows where the `CommitmentDiscountId` is the `ResourceId`? 3. With commitment/negotiated discount definitions altered, is it clear that current/planned `CommitmentDiscount*` columns are relevant for commitment discounts and *not* negotiated discounts? ## UPDATE (8/21/24) 1. Includes a recurring purchase for each charge period of the term for No/Partial Upfront commitments - No Upfront Purchase - has all units for the charge period - Partial Upfront Purchase - has 1/2 of the units for each charge period 2. Reverts changing guidance around these `{List,Contracted}{Cost,UnitPrice}` and `Pricing{Quantity,Unit}` columns. 3. Adds additional guidance commitment discount purchase is one-time vs. recurring 4. Adds additional phrasing to differentiate commitment vs negotiated discounts in each CommitmentDiscount* column. 5. Removes edit to resource name to further minimize pr size (for now) ## Update (8/22/24) 1. Changes to the ResourceId column have been reverted (no clause for ResourceId to be null with an unused commitment discount) ## Update (8/31/24) Given that this pr was not fully approved on 8/30, and there was considerable feedback (but less time) to merge `CommitmentDiscountConsumedQuantity` and `CommitmentDiscountPurchasedQuantity` into 1 column, I've gone ahead with this change to form column: `CommitmentDiscountQuantity`. Practitioners can stil filter to purchases and committed usage like: - Purchases: `ChargeCategory = 'Purchase' AND CommitmentDiscountId IS NOT NULL` - Committed Usage (Used): `ChargeCategory = 'Usage' AND CommitmentDiscountStatus = 'Used' AND CommitmentDiscountId IS NOT NULL` - Committed Usage (Unused): `ChargeCategory = 'Usage' AND CommitmentDiscountStatus = 'Unused' AND CommitmentDiscountId IS NOT NULL`. ## Update (9/3/24) - Added a brief paragraph around size-flexibility within `CommitmentDiscountQuantity` - Added additional glossary terms: `size-flexibility`, `instance-family`, `instance-type`, `instance-type-ratio`. - `instance-type-ratio` is the proposal for a generic, "FOCUS" term for `normalization factor` (AWS), or `size flexibility ratio` (Azure) This change is meant to reduce the number of proposed columns *without* changing *any* (meaningful) intent of the previous versions with 2 quantity columns. The last commit to this pr encapsulates this entire change and can be backed out if the group does not approve of this iteration. ## Update (9/10/24) - Further generalize "size-flexibility" as "commitment flexibility" and tie to provider requirements - Further generalize unit suggestions # Sample Data https://docs.google.com/spreadsheets/d/1AYDPZ4rl90PPEbyQJUaGCUSwZ4s_sfy-8sO2KyNq0aM/edit?pli=1&gid=1976106562#gid=1976106562 # Normative Text (original version, adopted into pr) https://docs.google.com/spreadsheets/d/1AYDPZ4rl90PPEbyQJUaGCUSwZ4s_sfy-8sO2KyNq0aM/edit?pli=1&gid=464941124#gid=464941124 --------- Co-authored-by: Irena Jurica Co-authored-by: Udam Dewaraja Co-authored-by: Graham Co-authored-by: Larry Advey <104788770+ljadvey@users.noreply.github.com> Co-authored-by: Michael Flanakin --- specification/attributes/discount_handling.md | 16 +++--- specification/columns/columns.mdpp | 2 + .../columns/commitmentdiscountcategory.md | 2 +- specification/columns/commitmentdiscountid.md | 4 +- .../columns/commitmentdiscountname.md | 2 +- .../columns/commitmentdiscountquantity.md | 52 +++++++++++++++++++ .../columns/commitmentdiscountstatus.md | 2 +- .../columns/commitmentdiscounttype.md | 2 +- .../columns/commitmentdiscountunit.md | 42 +++++++++++++++ specification/columns/consumedquantity.md | 12 +++-- specification/columns/consumedunit.md | 12 +++-- specification/columns/contractedcost.md | 2 +- specification/columns/contractedunitprice.md | 4 +- specification/columns/effectivecost.md | 1 + specification/columns/pricingcategory.md | 6 +-- specification/columns/pricingunit.md | 2 +- specification/glossary.md | 14 ++++- .../columns/commitmentdiscountquantity.md | 25 +++++++++ .../columns/commitmentdiscountunit.md | 23 ++++++++ 19 files changed, 197 insertions(+), 28 deletions(-) create mode 100644 specification/columns/commitmentdiscountquantity.md create mode 100644 specification/columns/commitmentdiscountunit.md create mode 100644 supporting_content/columns/commitmentdiscountquantity.md create mode 100644 supporting_content/columns/commitmentdiscountunit.md diff --git a/specification/attributes/discount_handling.md b/specification/attributes/discount_handling.md index be585c284..d301e51cf 100644 --- a/specification/attributes/discount_handling.md +++ b/specification/attributes/discount_handling.md @@ -1,10 +1,10 @@ # Discount Handling -A discount is a pricing construct where providers offer a reduced price for [*services*](#glossary:service). Providers may have many types of discounts, including but not limited to commercially negotiated discounts, commitment discounts when you agree to a certain amount of usage or spend, and bundled discounts where you receive free or discounted usage of one product or *service* based on the usage of another. Discount Handling is commonly used in scenarios like verifying discounts were applied and calculating cost savings. +A discount is a pricing construct where providers offer a reduced price for [*services*](#glossary:service). Providers may have many types of discounts, including but not limited to commercially [*negotiated discounts*](#glossary:negotiated-discount), [*commitment discounts*](#glossary:commitment-discount) when you agree to a certain amount of usage or spend, and bundled discounts where you receive free or discounted usage of one product or *service* based on the usage of another. Discount Handling is commonly used in scenarios like verifying discounts were applied and calculating cost savings. -Some discount offers can be purchased from a provider to get reduced prices. The most common example is a commitment discount, where you "purchase" a commitment to use or spend a specific amount within a period. When a commitment isn't fully utilized, the unused amount reduces the potential savings from the discount and can even result in paying higher costs than without the discount. Due to this risk, unused commitment amounts need to be clearly identifiable at a granular level. To facilitate this, unused commitments are recorded with a separate row for each charge period where the commitment was not fully utilized. In order to show the impact of purchased discounts on each discounted row, discount purchases need the purchase amount the be amortized over the term the discount is applied to (e.g., 1 year) with each charge period split and applied to each row that received the discount. +Some discount offers can be purchased from a provider to get reduced prices. The most common example is a *commitment discount*, where you "purchase" a commitment to use or spend a specific amount within a period. When a commitment isn't fully utilized, the unused amount reduces the potential savings from the discount and can even result in paying higher costs than without the discount. Due to this risk, unused commitment amounts need to be clearly identifiable at a granular level. To facilitate this, unused commitments are recorded with a separate row for each charge period where the commitment was not fully utilized. To show the impact of purchased discounts on each discounted row, discount purchases need the purchase amount to be amortized over the [*term*](#glossary:term) the discount is applied to (e.g., 1 year) with each [*charge period*](#glossary:chargeperiod) split and applied to each row that received the discount. -Amortization is a process used to break down and spread purchase costs over a period of time or term of use. When a purchase is applicable to resources, like commitment discounts, the amortized cost of a resource takes the initial payment and term into account and distributes it out based on the resource's usage, attributing the prorated cost for each unit of billing. Amortization enables users of billing data to distribute purchase charges to the appropriate audience in support of cost allocation efforts. Discount Handling for purchased commitments is commonly used for scenarios like calculating utilization and implementing chargeback for the purchase amount. +Amortization is a process used to break down and spread purchase costs over a period of time or *term* of use. When a purchase is applicable to resources, like *commitment discounts*, the amortized cost of a resource takes the initial payment and *term* into account and distributes it out based on the resource's usage, attributing the prorated cost for each unit of billing. Amortization enables users of billing data to distribute purchase charges to the appropriate audience in support of cost allocation efforts. Discount Handling for purchased commitments is commonly used for scenarios like calculating utilization and implementing chargeback for the purchase amount. While providers may use different terms to describe discounts, FOCUS identifies a discount as being a reduced price applied directly to a row. Any price or cost reductions that are awarded after the fact are identified as a "Credit" Charge Category. One example might be when a provider offers a reduced rate after passing a certain threshold of usage or spend. @@ -29,15 +29,15 @@ Indicates how to include and apply discounts to usage charges or rows in a FOCUS * Multiple discounts MAY apply to a row, but they MUST apply to the entire charge covered by that row. * If a discount only applies to a portion of a charge, then the discounted portion of the charge MUST be split into a separate row. * Each discount MUST be identifiable using existing FOCUS columns. - * Rows with a commitment discount applied to them MUST include a CommitmentDiscountId. + * Rows with a *commitment discount* applied to them MUST include a CommitmentDiscountId. * If a provider applies a discount that cannot be represented by a FOCUS column, they SHOULD include additional columns to identify the source of the discount. -* Purchased discounts (e.g., commitment discounts) MUST be amortized. +* Purchased discounts (e.g., *commitment discounts*) MUST be amortized. * The BilledCost MUST be 0 for any row where the commitment covers the entire cost for the charge period. * The EffectiveCost MUST include the portion of the amortized purchase cost that applies to this row. - * The sum of the EffectiveCost for all rows where CommitmentDiscountStatus is "Used" or "Unused" for each CommitmentDiscountId over the entire duration of the commitment MUST be the same as the total BilledCost of the commitment discount. - * The CommitmentDiscountId and ResourceId MUST be set to the ID assigned to the commitment discount. ChargeCategory MUST be set to "Purchase" on rows that represent a purchase of a commitment discount. + * The sum of the EffectiveCost for all rows where CommitmentDiscountStatus is "Used" or "Unused" for each CommitmentDiscountId over the entire duration of the commitment MUST be the same as the total BilledCost of the *commitment discount*. + * The CommitmentDiscountId and ResourceId MUST be set to the ID assigned to the *commitment discount*. ChargeCategory MUST be set to "Purchase" on rows that represent a purchase of a *commitment discount*. * CommitmentDiscountStatus MUST be "Used" for ChargeCategory "Usage" rows that received a reduced price from a commitment. CommitmentDiscountId MUST be set to the ID assigned to the discount. ResourceId MUST be set to the ID of the resource that received the discount. - * If a commitment is not fully utilized, the provider MUST include a row that represents the unused portion of the commitment for that charge period. These rows MUST be represented with CommitmentDiscountStatus set to "Unused" and ChargeCategory set to "Usage". Such rows MUST have their CommitmentDiscountId and ResourceId set to the ID assigned to the commitment discount. + * If a commitment is not fully utilized, the provider MUST include a row that represents the unused portion of the commitment for that *charge period*. These rows MUST be represented with CommitmentDiscountStatus set to "Unused" and ChargeCategory set to "Usage". Such rows MUST have their CommitmentDiscountId and ResourceId set to the ID assigned to the *commitment discount*. * Credits that are applied after the fact MUST use a ChargeCategory of "Credit". ## Exceptions diff --git a/specification/columns/columns.mdpp b/specification/columns/columns.mdpp index 42fca6745..7b1e126a6 100644 --- a/specification/columns/columns.mdpp +++ b/specification/columns/columns.mdpp @@ -22,6 +22,8 @@ The FOCUS specification defines a group of columns that provide qualitative valu !INCLUDE "commitmentdiscountname.md",1 !INCLUDE "commitmentdiscountstatus.md",1 !INCLUDE "commitmentdiscounttype.md",1 +!INCLUDE "commitmentdiscountquantity.md",1 +!INCLUDE "commitmentdiscountunit.md",1 !INCLUDE "consumedquantity.md",1 !INCLUDE "consumedunit.md",1 !INCLUDE "contractedcost.md",1 diff --git a/specification/columns/commitmentdiscountcategory.md b/specification/columns/commitmentdiscountcategory.md index 70c08b180..46f6d2338 100644 --- a/specification/columns/commitmentdiscountcategory.md +++ b/specification/columns/commitmentdiscountcategory.md @@ -1,6 +1,6 @@ # Commitment Discount Category -Commitment Discount Category indicates whether the [*commitment discount*](#glossary:commitment-discount) identified in the CommitmentDiscountId column is based on usage quantity or cost (aka "spend"). +Commitment Discount Category indicates whether the [*commitment discount*](#glossary:commitment-discount)identified in the CommitmentDiscountId column is based on usage quantity or cost (aka "spend"). The CommitmentDiscountCategory column is only applicable to *commitment discounts* and not [*negotiated discounts*](#glossary:negotiated-discount). The CommitmentDiscountCategory column MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. This column MUST be of type String, MUST be null when [CommitmentDiscountId](#commitmentdiscountid) is null, and MUST NOT be null when CommitmentDiscountId is not null. The CommitmentDiscountCategory MUST be one of the allowed values. diff --git a/specification/columns/commitmentdiscountid.md b/specification/columns/commitmentdiscountid.md index 30e99853f..94eb9d435 100644 --- a/specification/columns/commitmentdiscountid.md +++ b/specification/columns/commitmentdiscountid.md @@ -1,8 +1,8 @@ # Commitment Discount ID -A Commitment Discount ID is the identifier assigned to a [*commitment discount*](#glossary:commitment-discount) by the provider. Commitment Discount ID is commonly used for scenarios like chargeback for *commitments* and savings per *commitment discount*. +A Commitment Discount ID is the identifier assigned to a [*commitment discount*](#glossary:commitment-discount) by the provider. Commitment Discount ID is commonly used for scenarios like chargeback for *commitments* and savings per *commitment discount*. The CommitmentDiscountId column is only applicable to *commitment discounts* and not [*negotiated discounts*](#glossary:negotiated-discount). -The CommitmentDiscountId column MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. This column MUST be of type String and MUST NOT contain null values when a charge is related to a *commitment discount*. When a charge is not associated with a *commitment discount*, the column MUST be null. CommitmentDiscountId MUST be unique within the provider. +The CommitmentDiscountId column MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. This column MUST be of type String and MUST NOT contain null values when a charge is related to a *commitment discount*. When a charge is not associated with a *commitment discount*, the column MUST be null. CommitmentDiscountId MUST ensure global uniqueness within the provider and SHOULD be a fully-qualified identifier. ## Column ID diff --git a/specification/columns/commitmentdiscountname.md b/specification/columns/commitmentdiscountname.md index 97abc352d..66c8b1a84 100644 --- a/specification/columns/commitmentdiscountname.md +++ b/specification/columns/commitmentdiscountname.md @@ -1,6 +1,6 @@ # Commitment Discount Name -A Commitment Discount Name is the display name assigned to a [*commitment discount*](#glossary:commitment-discount). +A Commitment Discount Name is the display name assigned to a [*commitment discount*](#glossary:commitment-discount). The CommitmentDiscountName column is only applicable to *commitment discounts* and not [*negotiated discounts*](#glossary:negotiated-discount). The CommitmentDiscountName column MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. This column MUST be of type String. The CommitmentDiscountName value MUST be null if the charge is not related to a *commitment discount* and MAY be null if a display name cannot be assigned to a *commitment discount*. CommitmentDiscountName MUST NOT be null if a display name can be assigned to a *commitment discount*. diff --git a/specification/columns/commitmentdiscountquantity.md b/specification/columns/commitmentdiscountquantity.md new file mode 100644 index 000000000..45f4922c8 --- /dev/null +++ b/specification/columns/commitmentdiscountquantity.md @@ -0,0 +1,52 @@ +# Commitment Discount Quantity + +Commitment Discount Quantity is the amount of a [*commitment discount*](#commitment-discount) purchased or accounted for in *commitment discount* related [*rows*](#glossary:row) that is denominated in [*Commitment Discount Units*](#glossary:commitmentdiscountunit). The aggregated Commitment Discount Quantity across purchase records, pertaining to a particular [Commitment Discount ID](#commitmentdiscountid) during its [*term*](#glossary:term), represents the total *Commitment Discount Units* acquired with that commitment discount. For committed usage, the Commitment Discount Quantity is either the number of *Commitment Discount Units* consumed by a [*row*](glossary:#row) that is covered by a *commitment discount* or is the unused portion of a *commitment discount* over a *charge period*. Commitment Discount Quantity is commonly used in *commitment discount* analysis and optimization use cases and only applies to *commitment discounts*, not [*negotiated discounts*](#glossary:negotiated-discount). + +When *CommitmentDiscountCategory* is "Usage" (usage-based *commitment discounts*), the Commitment Discount Quantity reflects the predefined amount of usage purchased or consumed. If *commitment flexibility* is applicable, this value may be further transformed based on additional, provider-specific requirements. When *CommitmentDiscountCategory* is "Spend" (spend-based *commitment discounts*), the Commitment Discount Quantity reflects the predefined amount of spend purchased or consumed. + +**Important:** When aggregating Commitment Discount Quantity for utilization calculations, it's important to exclude *commitment discount* purchases (i.e. when *ChargeCategory* is "Purchase") that are paid to cover future eligible charges (e.g., *Commitment Discount*). This exclusion helps prevent double counting of these quantities in the aggregation. + +The CommitmentDiscountQuantity column adheres to the following requirements: + +* CommitmentDiscountQuantity MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. +* CommitmentDiscountQuantity MUST be of type Decimal and MUST conform to [Numeric Format](#numericformat) requirements. +* CommitmentDiscountQuantity MAY be negative if [*ChargeClass*](#chargeclass) is "Correction". + +In cases where the *ChargeCategory* is "Purchase" and [*CommitmentDiscountId*](#commitmentdiscountid) is not null, the following applies: + +* When [*ChargeFrequency*](#chargefrequency) is "One-Time", and *CommitmentDiscountId* is not null, CommitmentDiscountQuantity MUST be the positive quantity of *CommitmentDiscountUnits*, paid fully or partially upfront, that is eligible for consumption over the *commitment discount's* *term*. +* When *ChargeFrequency* is "Recurring", and *CommitmentDiscountId* is not null, CommitmentDiscountQuantity MUST be the positive quantity of *CommitmentDiscountUnits* that is eligible for consumption for each *charge period* that corresponds with the purchase. + +In cases where the *ChargeCategory* is "Usage" and *CommitmentDiscountId* is not null, the following applies: + +* When *CommitmentDiscountStatus* is "Used", and *ChargeClass* is not "Correction", CommitmentDiscountQuantity MUST be the positive, metered quantity of *CommitmentDiscountUnits* that is consumed over the *row's* *charge period*. +* When *CommitmentDiscountStatus* is "Unused", and *ChargeClass* is not "Correction", CommitmentDiscountQuantity MUST be the remaining, positive, unused quantity of *CommitmentDiscountUnits* for the *row's* *charge period*. + +CommitmentDiscountQuantity MUST be null for all other *ChargeCategory* values. + +## Column ID + +CommitmentDiscountQuantity + +## Display Name + +Commitment Discount Quantity + +## Description + +The amount of a *commitment discount* purchased or accounted for in *commitment discount* related *rows* that is denominated in *Commitment Discount Units*. + +## Content constraints + +| Constraint | Value | +|:----------------|:-----------------| +| Column type | Dimension | +| Feature level | Conditional | +| Allows nulls | True | +| Data type | Decimal | +| Value format | [Numeric Format](#numericformat) | +| Number range | Any valid decimal value | + +## Introduced (version) + +1.1 diff --git a/specification/columns/commitmentdiscountstatus.md b/specification/columns/commitmentdiscountstatus.md index 8353d0284..7a92f8967 100644 --- a/specification/columns/commitmentdiscountstatus.md +++ b/specification/columns/commitmentdiscountstatus.md @@ -1,6 +1,6 @@ # Commitment Discount Status -Commitment Discount Status indicates whether the charge corresponds with the consumption of the [*commitment discount*](#glossary:commitment-discount) identified in the CommitmentDiscountId column or the unused portion of the committed amount. +Commitment Discount Status indicates whether the charge corresponds with the consumption of a [*commitment discount*](#glossary:commitment-discount) identified in the CommitmentDiscountId column or the unused portion of the committed amount. The CommitmetnDiscountStatus column is only applicable to *commitment discounts* and not [*negotiated discounts*](#glossary:negotiated-discount). The CommitmentDiscountStatus column MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. This column MUST be of type String, MUST be null when [CommitmentDiscountId](#commitmentdiscountid) is null, and MUST NOT be null when CommitmentDiscountId is not null and [Charge Category](#chargecategory) is "Usage". The CommitmentDiscountCategory MUST be one of the allowed values. diff --git a/specification/columns/commitmentdiscounttype.md b/specification/columns/commitmentdiscounttype.md index 48e61926e..23cae2212 100644 --- a/specification/columns/commitmentdiscounttype.md +++ b/specification/columns/commitmentdiscounttype.md @@ -1,6 +1,6 @@ # Commitment Discount Type -Commitment Discount Type is a provider-assigned name to identify the type of [*commitment discount*](#glossary:commitment-discount) applied to the [*row*](#glossary:row). +Commitment Discount Type is a provider-assigned name to identify the type of [*commitment discount*](#glossary:commitment-discount) applied to the [*row*](#glossary:row). The CommitmentDiscountType column is only applicable to *commitment discounts* and not [*negotiated discounts*](#glossary:negotiated-discount). The CommitmentDiscountType column MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. This column MUST be of type String, MUST be null when [CommitmentDiscountId](#commitmentdiscountid) is null, and MUST NOT be null when CommitmentDiscountId is not null. diff --git a/specification/columns/commitmentdiscountunit.md b/specification/columns/commitmentdiscountunit.md new file mode 100644 index 000000000..d4c9efb9d --- /dev/null +++ b/specification/columns/commitmentdiscountunit.md @@ -0,0 +1,42 @@ +# Commitment Discount Unit + +Commitment Discount Unit represents the provider-specified measurement unit indicating how a provider measures the [Commitment Discount Quantity](#commitmentdiscountquantity) of a [*commitment discount*](#glossary:commitment-discount). The CommitmentDiscountUnit column is only applicable to *commitment discounts* and not [*negotiated discounts*](#glossary:negotiated-discount). + +The CommitmentDiscountUnit column adheres to the following requirements: + +* CommitmentDiscountUnit MUST be present in a FOCUS dataset when the provider supports [*commitment discounts*](#glossary:commitment-discount). +* CommitmentDiscountUnit MUST be of type String, and the units of measure used in CommitmentDiscountUnit SHOULD adhere to the values and format requirements specified in the [UnitFormat](#unitformat) attribute. +* The CommitmentDiscountUnit MUST be the same across all *rows* where *CommitmentDiscountQuantity* has the same [*CommitmentDiscountId*](#commitmentdiscountid). +* CommitmentDiscountUnit MUST NOT be null when *CommitmentDiscountId* is not null. +* CommitmentDiscountUnit MUST be null in all other cases. + +In cases where the CommitmentDiscountUnit is not null, the following applies: + +* The CommitmentDiscountUnit MUST represent the unit used to measure the *commitment discount*. +* When accounting for *commitment flexibility*, the CommitmentDiscountUnit value SHOULD reflect this consideration. + +## Column ID + +CommitmentDiscountUnit + +## Display Name + +Commitment Discount Unit + +## Description + +The provider-specified measurement unit indicating how a provider measures the *Commitment Discount Quantity* of a *commitment discount*. + +## Content constraints + +| Constraint | Value | +|:----------------|:-----------------| +| Column type | Dimension | +| Feature level | Conditional | +| Allows nulls | True | +| Data type | String | +| Value format | [Unit Format](#unitformat)| + +## Introduced (version) + +1.1 diff --git a/specification/columns/consumedquantity.md b/specification/columns/consumedquantity.md index faab3c0fa..b7ea4d2d8 100644 --- a/specification/columns/consumedquantity.md +++ b/specification/columns/consumedquantity.md @@ -1,8 +1,14 @@ # Consumed Quantity -The Consumed Quantity represents the volume of a given SKU associated with a [*resource*](#glossary:resource) or [*service*](#glossary:service) used, based on the [Consumed Unit](#consumedunit). Consumed Quantity is often derived at a finer granularity or over a different time interval when compared to the [Pricing Quantity](#pricingquantity) (complementary to [Pricing Unit](#pricingunit)) and focuses on *resource* and *service* consumption, not pricing and cost. +The Consumed Quantity represents the volume of a given SKU associated with a metered [*resource*](#glossary:resource) or [*service*](#glossary:service) used, based on the [Consumed Unit](#consumedunit). Consumed Quantity is often derived at a finer granularity or over a different time interval when compared to the [Pricing Quantity](#pricingquantity) (complementary to [Pricing Unit](#pricingunit)) and focuses on metered *resource* and *service* consumption, not pricing and cost. -ConsumedQuantity column MUST be present in a FOCUS dataset when the provider supports the measurement of usage. This column MUST NOT be null if [ChargeCategory](#chargecategory) is "Usage" and [ChargeClass](#chargeclass) is not "Correction". This column MUST be null for other ChargeCategory values. This column MUST be of type Decimal and MUST conform to [Numeric Format](#numericformat) requirements. The value MAY be negative in cases where [ChargeClass](#chargeclass) is "Correction". +The ConsumedQuantity column adheres to the following requirements: + +* ConsumedQuantity MUST be present in a FOCUS dataset when the provider supports the measurement of usage. +* ConsumedQuantity MUST be of type Decimal and MUST conform to [Numeric Format](#numericformat) requirements. +* ConsumedQuantity MUST NOT be null if [ChargeCategory](#chargecategory) is "Usage" and [ChargeClass](#chargeclass) is not "Correction". +* ConsumedQuantity MUST be null if [CommitmentDiscountStatus](#commitmentdiscountstatus) is "Unused" or for other *ChargeCategory* values. +* ConsumedQuantity MAY be negative or null in cases where *ChargeClass* is "Correction". ## Column ID @@ -14,7 +20,7 @@ Consumed Quantity ## Description -The volume of a given SKU associated with a *resource* or *service* used, based on the Consumed Unit. +The volume of a given SKU associated with a metered *resource* or *service* used, based on the Consumed Unit. ## Content constraints diff --git a/specification/columns/consumedunit.md b/specification/columns/consumedunit.md index cb36de660..7fcb4a37a 100644 --- a/specification/columns/consumedunit.md +++ b/specification/columns/consumedunit.md @@ -1,8 +1,14 @@ # Consumed Unit -The Consumed Unit represents a provider-specified measurement unit indicating how a provider measures usage of a given SKU associated with a [*resource*](#glossary:resource) or [*service*](#glossary:service). Consumed Unit complements the [Consumed Quantity](#consumedquantity) metric. It is often listed at a finer granularity or over a different time interval when compared to [Pricing Unit](#pricingunit) (complementary to [Pricing Quantity](#pricingquantity)), and focuses on *resource* and *service* consumption, not pricing and cost. +The Consumed Unit represents a provider-specified measurement unit indicating how a provider measures usage of a given SKU associated with a metered [*resource*](#glossary:resource) or [*service*](#glossary:service). Consumed Unit complements the [Consumed Quantity](#consumedquantity) metric. It is often listed at a finer granularity or over a different time interval when compared to [Pricing Unit](#pricingunit) (complementary to [Pricing Quantity](#pricingquantity)), and focuses on metered *resource* and *service* consumption, not pricing and cost. -The ConsumedUnit column MUST be present in a FOCUS dataset when the provider supports the measurement of usage. This column MUST be of type String. ConsumedUnit MUST NOT be null if [ChargeCategory](#chargecategory) is "Usage" and [ChargeClass](#chargeclass) is not "Correction". This column MUST be null for other ChargeCategory values. Units of measure used in ConsumedUnit SHOULD adhere to the values and format requirements specified in the [UnitFormat](#unitformat) attribute. The ConsumedUnit column MUST NOT be used to determine values related to any pricing or cost metrics. +The ConsumedUnit column adheres to the following requirements: + +* ConsumedUnit MUST be present in the billing data when the provider supports the measurement of usage. +* ConsumedUnit MUST be of type String, and the units of measure used in ConsumedUnit SHOULD adhere to the values and format requirements specified in the [UnitFormat](#unitformat) attribute. +* ConsumedUnit MUST NOT be null if [ChargeCategory](#chargecategory) is "Usage" and [ChargeClass](#chargeclass) is not "Correction". +* When *ChargeCategory* is not "Usage", or *ChargeCategory* is "Usage" and [CommitmentDiscountStatus](#commitmentdiscountstatus) is "Unused", ConsumedUnit MUST be null when ChargeClass is not "Correction". +* ConsumedUnit MAY be null if *ChargeCategory* is "Usage" and ChargeClass is "Correction". ## Column ID @@ -14,7 +20,7 @@ Consumed Unit ## Description -Provider-specified measurement unit indicating how a provider measures usage of a given SKU associated with a *resource* or *service*. +Provider-specified measurement unit indicating how a provider measures usage of a given SKU associated with a metered *resource* or *service*. ## Content constraints diff --git a/specification/columns/contractedcost.md b/specification/columns/contractedcost.md index 12912f761..e44233c8e 100644 --- a/specification/columns/contractedcost.md +++ b/specification/columns/contractedcost.md @@ -1,6 +1,6 @@ # Contracted Cost -Contracted Cost represents the cost calculated by multiplying [*contracted unit price*](#glossary:contracted-unit-price) and the corresponding [Pricing Quantity](#pricingquantity). Contracted Cost is denominated in the [Billing Currency](#billingcurrency) and is commonly used for calculating savings based on negotiation activities, by comparing it with [List Cost](#listcost). If negotiated discounts are not applicable, the Contracted Cost defaults to the List Cost. +Contracted Cost represents the cost calculated by multiplying [*contracted unit price*](#glossary:contracted-unit-price) and the corresponding [Pricing Quantity](#pricingquantity). Contracted Cost is denominated in the [Billing Currency](#billingcurrency) and is commonly used for calculating savings based on negotiation activities, by comparing it with [List Cost](#listcost). If [*negotiated discounts*](#glossary:negotiated-discount) are not applicable, the Contracted Cost defaults to the List Cost. **Important:** When aggregating Contracted Cost for savings calculations, it's important to exclude either one-time or recurring charges ([Charge Category](#chargecategory) "Purchase") that are paid to cover future eligible charges (e.g., [Commitment Discount](#glossary:commitment-discount)) or the covered charges themselves. This exclusion helps prevent double counting of these charges in the aggregation. Which set of charges to exclude depends on whether cost are aggregated on a billed basis (exclude covered charges) or accrual basis (exclude Purchases for future charges). For instance, charges categorized as [Charge Category](#chargecategory) "Purchase" and their related [Charge Category](#chargecategory) "Tax" charges for a Commitment Discount might be excluded from an accrual basis cost aggregation of Contracted Cost. This is because the "Usage" and "Tax" charge records provided during the term of the commitment discount already specify the Contracted Cost. Purchase charges that cover future eligible charges can be identified by filtering for [Charge Category](#chargecategory) "Purchase" records with a [Billed Cost](#billedcost) greater than 0 and an [Effective Cost](#effectivecost) equal to 0. diff --git a/specification/columns/contractedunitprice.md b/specification/columns/contractedunitprice.md index faf177d32..4061d0ec3 100644 --- a/specification/columns/contractedunitprice.md +++ b/specification/columns/contractedunitprice.md @@ -1,8 +1,8 @@ # Contracted Unit Price -The Contracted Unit Price represents the agreed-upon unit price for a single [Pricing Unit](#pricingunit) of the associated SKU, inclusive of negotiated discounts, if present, while excluding negotiated commitment discounts or any other discounts. This price is denominated in the [Billing Currency](#billingcurrency). The Contracted Unit Price is commonly used for calculating savings based on negotiation activities. If negotiated discounts are not applicable, the Contracted Unit Price defaults to the [List Unit Price](#listunitprice). +The Contracted Unit Price represents the agreed-upon unit price for a single [Pricing Unit](#pricingunit) of the associated SKU, inclusive of [*negotiated discounts*](#glossary:negotiated-discount), if present, while excluding negotiated [*commitment discounts*](#glossary:commitment-discount) or any other discounts. This price is denominated in the [Billing Currency](#billingcurrency). The Contracted Unit Price is commonly used for calculating savings based on negotiation activities. If negotiated discounts are not applicable, the Contracted Unit Price defaults to the [List Unit Price](#listunitprice). -The ContractedUnitPrice column MUST be present in a FOCUS dataset when the provider supports negotiated pricing concept. This column MUST be a Decimal within the range of non-negative decimal values, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When ContractedUnitPrice is present and not null, multiplying ContractedUnitPrice by [PricingQuantity](#pricingquantity) MUST equal [ContractedCost](#contractedcost), except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. +The ContractedUnitPrice column MUST be present in a FOCUS dataset when the provider supports negotiated pricing concepts. This column MUST be a Decimal within the range of non-negative decimal values, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When ContractedUnitPrice is present and not null, multiplying ContractedUnitPrice by [PricingQuantity](#pricingquantity) MUST equal [ContractedCost](#contractedcost), except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. ## Column ID diff --git a/specification/columns/effectivecost.md b/specification/columns/effectivecost.md index eb5b28887..45424f4ff 100644 --- a/specification/columns/effectivecost.md +++ b/specification/columns/effectivecost.md @@ -13,6 +13,7 @@ In cases where the [ChargeCategory](#chargecategory) is not "Usage" or "Purchase * The EffectiveCost MUST be calculated based on the EffectiveCost of the related charges if the charge is calculated based on other charges (e.g. [ChargeCategory](#chargecategory) is "Tax"). * The EffectiveCost MUST match the [BilledCost](#billedcost) if the charge is unrelated to other charges (e.g. [ChargeCategory](#chargecategory) is "Credit"). +* When CommitmentDiscountStatus is "Unused", the EffectiveCost MUST be the total committed cost consumed for the given charge period minus related usage charges. ## Column ID diff --git a/specification/columns/pricingcategory.md b/specification/columns/pricingcategory.md index 7f881fa46..b929a6747 100644 --- a/specification/columns/pricingcategory.md +++ b/specification/columns/pricingcategory.md @@ -1,6 +1,6 @@ # Pricing Category -Pricing Category describes the pricing model used for a charge at the time of use or purchase. It can be useful for distinguishing between charges incurred at the [*list unit price*](#glossary:list-unit-price) or a reduced price and exposing optimization opportunities, like increasing [commitment discount](#glossary:commitment-discount) coverage. +Pricing Category describes the pricing model used for a charge at the time of use or purchase. It can be useful for distinguishing between charges incurred at the [*list unit price*](#glossary:list-unit-price) or a reduced price and exposing optimization opportunities, like increasing [*commitment discount*](#glossary:commitment-discount) coverage. The PricingCategory column adheres to the following requirements: @@ -38,9 +38,9 @@ Allowed values: | Value | Description | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Standard | Charges priced at the agreed upon rate for the billing account, including negotiated discounts. This includes any flat rate and volume/tiered pricing but does not include dynamic or commitment discount pricing. | +| Standard | Charges priced at the agreed upon rate for the billing account, including [*negotiated discounts*](#glossary:negotiated-discount). This includes any flat rate and volume/tiered pricing but does not include dynamic or *commitment discount* pricing. | | Dynamic | Charges priced at a variable rate determined by the provider. This includes any product or service with a unit price the provider can change without notice, like interruptible or low priority resources. | -| Committed | Charges with reduced prices due to a commitment discount specified by the Commitment Discount ID. | +| Committed | Charges with reduced prices due to a *commitment discount* specified by the Commitment Discount ID. | | Other | Charges priced in a way not covered by another pricing category. | ## Introduced (version) diff --git a/specification/columns/pricingunit.md b/specification/columns/pricingunit.md index 73e38c943..3b4fca8db 100644 --- a/specification/columns/pricingunit.md +++ b/specification/columns/pricingunit.md @@ -1,6 +1,6 @@ # Pricing Unit -The Pricing Unit represents a provider-specified measurement unit for determining unit prices, indicating how the provider rates measured usage and purchase quantities after applying pricing rules like [*block pricing*](#glossary:block-pricing). Common examples include the number of hours for compute appliance runtime (e.g. `Hours`), gigabyte-hours for a storage appliance (e.g., `GB-Hours`), or an accumulated count of requests for a network appliance or API service (e.g., `1000 Requests`). Pricing Unit complements the [Pricing Quantity](#pricingquantity) metric. Distinct from the [Consumed Unit](#Consumedunit), it focuses on pricing and cost, not [*resource*](#glossary:resource) and [*service*](#glossary:service) consumption, often at a coarser granularity. +The Pricing Unit represents a provider-specified measurement unit for determining unit prices, indicating how the provider rates measured usage and purchase quantities after applying pricing rules like [*block pricing*](#glossary:block-pricing). Common examples include the number of hours for compute appliance runtime (e.g. `Hours`), gigabyte-hours for a storage appliance (e.g., `GB-Hours`), or an accumulated count of requests for a network appliance or API service (e.g., `1000 Requests`). Pricing Unit complements the [Pricing Quantity](#pricingquantity) metric. Distinct from the [Consumed Unit](#consumedunit), it focuses on pricing and cost, not [*resource*](#glossary:resource) and [*service*](#glossary:service) consumption, often at a coarser granularity. The PricingUnit column MUST be present in a FOCUS dataset. This column MUST be of type String. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. Units of measure used in PricingUnit SHOULD adhere to the values and format requirements specified in the [UnitFormat](#unitformat) attribute. diff --git a/specification/glossary.md b/specification/glossary.md index 5ccf2cb4c..f3b4b56ce 100644 --- a/specification/glossary.md +++ b/specification/glossary.md @@ -50,7 +50,11 @@ A customer's agreement to consume a specific quantity of a service or resource o Commitment Discount -Also known as Commitment Discount, this is a commitment for an amount of usage or spend throughout a specified term, in exchange for discounted unit pricing on that amount. The commitment may be based on quantities of resource units or monetary value, with various payment options and time frames. +A billing discount model that offers reduced rates on preselected SKUs in exchange for an obligated usage or spend amount over a predefined term. Commitment discount purchases, made upfront and/or with recurring monthly payments are amortized evenly across predefined charge periods (i.e. hourly), and unused amounts cannot be carried over to subsequent charge periods. Commitment discounts are publicly available to customers without special contract arrangements. + +Commitment Flexibility + +A feature of [*commitment discounts*](#glossary:commitment-discount) that may further transform the predetermind amount of usage purchased or consumed based on additional, provider-specific requirements. Cloud Service Provider (CSP) @@ -104,6 +108,10 @@ A FOCUS-defined column that provides numeric values, allowing for aggregation op A company or organization that provides outsourced management and support of a range of IT services, such as network infrastructure, cybersecurity, cloud computing, and more. +Negotiated Discount + +A contractual agreement where a customer commits to specific spend or usage goals over a [*term*](#glossary:term) in exchange for discounted rates across varying SKUs. Unlike [*commitment discounts*](#glossary:commitment-discount), negotiated discounts are typically more customized to customer's accounts, can be utilized at varying frequencies, and may overlap with *commitment discounts*. + On-Demand A term that describes a service that is available and provided immediately or as needed, without requiring a pre-scheduled appointment or prior arrangement. In cloud computing, virtual machines can be created and terminated as needed, i.e. on demand. @@ -159,3 +167,7 @@ A metadata label assigned to a resource to provide information about it or to ca Tag Source A Resource or Provider-defined construct for grouping resources and/or other Provider-defined construct that a Tag can be assigned to. + +Term + +A duration of a contractual agreement like with a [*commitment discount*](#glossary:commitment-discount) or [*negotiated discount*](#glossary:negotiated-discount). diff --git a/supporting_content/columns/commitmentdiscountquantity.md b/supporting_content/columns/commitmentdiscountquantity.md new file mode 100644 index 000000000..78c9fbb38 --- /dev/null +++ b/supporting_content/columns/commitmentdiscountquantity.md @@ -0,0 +1,25 @@ +# Column: CommitmentDiscountQuantity + +## Example provider mappings + +Current column mappings found in available data sets: + +| Provider | Data set | Column | +|----------|----------|--------| +| AWS | CUR | reservation/UnusedQuantity (inverse), reservation/TotalReservedUnits, savingsPlan/UsedCommitment, savingsPlan/TotalCommitmentToDate | +| Google Cloud | BigQuery Billing Export | Not available | +| Microsoft | Cost Details | Not available | + +## Example usage scenarios + +Current values observed in billing data for various scenarios: + +AWS Reservation Utilization Rate: (1 - (reservation/UnusedQuantity / reservation/TotalReservedUnits)) * 100 +AWS Savings Plan Utilization Rate: savingsPlan/UsedCommitment / savingsPlan/TotalCommitmentToDate * 100 + +## Documentation +- AWS + - Reservation details - https://docs.aws.amazon.com/cur/latest/userguide/reservation-columns.html + - Savings Plans details - https://docs.aws.amazon.com/cur/latest/userguide/savingsplans-columns.html + + diff --git a/supporting_content/columns/commitmentdiscountunit.md b/supporting_content/columns/commitmentdiscountunit.md new file mode 100644 index 000000000..180d2919e --- /dev/null +++ b/supporting_content/columns/commitmentdiscountunit.md @@ -0,0 +1,23 @@ +# Column: CommitmentDiscountUnit + +## Example provider mappings + +Current column mappings found in available data sets: + +| Provider | Data set | Column | +|----------|----------|--------| +| AWS | CUR | Not available | +| Google Cloud | BigQuery Billing Export | Not available | +| Microsoft | Cost Details | Usage commitments: UnitOfMeasure
Spend commitments: BillingCurrency | + +## Example usage scenarios + +Current values observed in billing data for various scenarios: + +AWS Reservation Utilization Rate: (1 - (reservation/UnusedQuantity / reservation/TotalReservedUnits)) * 100 +AWS Savings Plan Utilization Rate: savingsPlan/UsedCommitment / savingsPlan/TotalCommitmentToDate * 100 + +## Documentation +- AWS + - Reservation details - https://docs.aws.amazon.com/cur/latest/userguide/reservation-columns.html + - Savings Plans details - https://docs.aws.amazon.com/cur/latest/userguide/savingsplans-columns.html From f3b6e29a879568f900b90f49515ca1aff34b2a8b Mon Sep 17 00:00:00 2001 From: Michael Flanakin Date: Thu, 12 Sep 2024 13:59:43 -0700 Subject: [PATCH 26/52] Fix CDStatus column reference (#538) Fixes an incorrect column name reference. No functional changes. --------- Co-authored-by: Joaquin --- specification/columns/commitmentdiscountstatus.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/columns/commitmentdiscountstatus.md b/specification/columns/commitmentdiscountstatus.md index 7a92f8967..edc382186 100644 --- a/specification/columns/commitmentdiscountstatus.md +++ b/specification/columns/commitmentdiscountstatus.md @@ -2,7 +2,7 @@ Commitment Discount Status indicates whether the charge corresponds with the consumption of a [*commitment discount*](#glossary:commitment-discount) identified in the CommitmentDiscountId column or the unused portion of the committed amount. The CommitmetnDiscountStatus column is only applicable to *commitment discounts* and not [*negotiated discounts*](#glossary:negotiated-discount). -The CommitmentDiscountStatus column MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. This column MUST be of type String, MUST be null when [CommitmentDiscountId](#commitmentdiscountid) is null, and MUST NOT be null when CommitmentDiscountId is not null and [Charge Category](#chargecategory) is "Usage". The CommitmentDiscountCategory MUST be one of the allowed values. +The CommitmentDiscountStatus column MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. This column MUST be of type String, MUST be null when [CommitmentDiscountId](#commitmentdiscountid) is null, and MUST NOT be null when CommitmentDiscountId is not null and [Charge Category](#chargecategory) is "Usage". CommitmentDiscountStatus MUST be one of the allowed values. ## Column ID From b5eeb1f1372971fb4466001184b283e43f72a83f Mon Sep 17 00:00:00 2001 From: Irena Jurica Date: Thu, 12 Sep 2024 23:01:31 +0200 Subject: [PATCH 27/52] FOCUS #532: PricingCategory update - Classify commitment discount purchase records as Standard instead of Committed (#533) **Lead Maintainer**: Irena Classify commitment discount purchase records as Standard instead of Committed, by rephrasing the following requirement: > * PricingCategory MUST be "Committed" when [CommitmentDiscountId](#commitmentdiscountid) is not null. New version: > * PricingCategory MUST be "Committed" when [CommitmentDiscountId](#commitmentdiscountid) is not null, except when ChargeCategory is "Purchase" and the [ResourceId](#resourceid) matches the CommitmentDiscountId. or > * PricingCategory MUST be "Committed" when [CommitmentDiscountId](#commitmentdiscountid) is not null, except when ChargeCategory is "Purchase" and the [ResourceId](#resourceid) matches the CommitmentDiscountId, representing a charge related to the purchase of that commitment discount. --------- Co-authored-by: Alex Hullah Co-authored-by: Michael Flanakin --- specification/columns/pricingcategory.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/columns/pricingcategory.md b/specification/columns/pricingcategory.md index b929a6747..1636622d9 100644 --- a/specification/columns/pricingcategory.md +++ b/specification/columns/pricingcategory.md @@ -8,7 +8,7 @@ The PricingCategory column adheres to the following requirements: * PricingCategory MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. * PricingCategory MUST be one of the allowed values. * PricingCategory MUST be "Standard" when pricing is predetermined at the agreed upon rate for the [billing account](#glossary:billing-account). -* PricingCategory MUST be "Committed" when [CommitmentDiscountId](#commitmentdiscountid) is not null. +* PricingCategory MUST be "Committed" when the charge is subject to an existing *commitment discount* and is not the purchase of the *commitment discount*. * PricingCategory MUST be "Dynamic" when pricing is determined by the provider and may change over time, regardless of predetermined agreement pricing. * PricingCategory MUST be "Other" when there is a pricing model but none of the allowed values apply. From c1f786fc7c8da2fba932723803d5f29808a2a304 Mon Sep 17 00:00:00 2001 From: Christopher Harris Date: Fri, 13 Sep 2024 15:24:51 -0400 Subject: [PATCH 28/52] Add 1 missing space between "commitment discount" and "identified" (#541) Old: `[*commitment discount*](#glossary:commitment-discount)identified` New: `[*commitment discount*](#glossary:commitment-discount) identified` --- specification/columns/commitmentdiscountcategory.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/columns/commitmentdiscountcategory.md b/specification/columns/commitmentdiscountcategory.md index 46f6d2338..357642cfc 100644 --- a/specification/columns/commitmentdiscountcategory.md +++ b/specification/columns/commitmentdiscountcategory.md @@ -1,6 +1,6 @@ # Commitment Discount Category -Commitment Discount Category indicates whether the [*commitment discount*](#glossary:commitment-discount)identified in the CommitmentDiscountId column is based on usage quantity or cost (aka "spend"). The CommitmentDiscountCategory column is only applicable to *commitment discounts* and not [*negotiated discounts*](#glossary:negotiated-discount). +Commitment Discount Category indicates whether the [*commitment discount*](#glossary:commitment-discount) identified in the CommitmentDiscountId column is based on usage quantity or cost (aka "spend"). The CommitmentDiscountCategory column is only applicable to *commitment discounts* and not [*negotiated discounts*](#glossary:negotiated-discount). The CommitmentDiscountCategory column MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. This column MUST be of type String, MUST be null when [CommitmentDiscountId](#commitmentdiscountid) is null, and MUST NOT be null when CommitmentDiscountId is not null. The CommitmentDiscountCategory MUST be one of the allowed values. From 20528627e6d6ea848f834c738d31c92c5e6c6ff4 Mon Sep 17 00:00:00 2001 From: rileyjenk Date: Thu, 19 Sep 2024 12:44:41 -0600 Subject: [PATCH 29/52] Improvements To Metadata (#514) Improvements to schema metadata including examples. --------- Co-authored-by: Christopher Harris Co-authored-by: Udam Dewaraja Co-authored-by: Shawn Alpay <77511110+salpaysenturus@users.noreply.github.com> Co-authored-by: Joaquin --- specification/appendix/appendix.mdpp | 1 + specification/appendix/examples/examples.mdpp | 5 + .../metadata/adding_new_columns_example.md | 78 ++++++++++ .../changing_column_metadata_example.md | 72 +++++++++ .../correcting_schema_errors_example.md | 72 +++++++++ .../metadata/data_generator_example.md | 20 +++ .../metadata/focus_version_changed_example.md | 72 +++++++++ ...nged_with_provider_version_used_example.md | 140 ++++++++++++++++++ .../examples/metadata/metadata_examples.mdpp | 24 +++ .../provider_version_changed_example.md | 76 ++++++++++ .../metadata/removing_columns_example.md | 72 +++++++++ .../metadata/schema_metadata_example.md | 61 ++++++++ .../schema_metadata_reference_example.md | 78 ++++++++++ .../data_generator/data_generator.mdpp | 8 + .../metadata/data_generator/datagenerator.md | 13 +- specification/metadata/metadata.mdpp | 6 +- .../column_definition/column_definition.mdpp | 4 + .../schema/column_definition/columnname.md | 9 ++ .../schema/column_definition/datatype.md | 9 ++ .../schema/column_definition/numberscale.md | 9 ++ .../column_definition/numericprecision.md | 9 ++ .../column_definition/providertagprefixes.md | 9 ++ .../column_definition/stringencoding.md | 9 ++ .../column_definition/stringmaxlength.md | 9 ++ specification/metadata/schema/creationdate.md | 9 ++ specification/metadata/schema/focusversion.md | 11 +- .../metadata/schema/providerversion.md | 26 ++++ specification/metadata/schema/schema.mdpp | 32 +++- specification/metadata/schema/schemaid.md | 11 +- .../metadata/schema_creation_scenarios.md | 13 ++ 30 files changed, 960 insertions(+), 7 deletions(-) create mode 100644 specification/appendix/examples/examples.mdpp create mode 100644 specification/appendix/examples/metadata/adding_new_columns_example.md create mode 100644 specification/appendix/examples/metadata/changing_column_metadata_example.md create mode 100644 specification/appendix/examples/metadata/correcting_schema_errors_example.md create mode 100644 specification/appendix/examples/metadata/data_generator_example.md create mode 100644 specification/appendix/examples/metadata/focus_version_changed_example.md create mode 100644 specification/appendix/examples/metadata/focus_version_changed_with_provider_version_used_example.md create mode 100644 specification/appendix/examples/metadata/metadata_examples.mdpp create mode 100644 specification/appendix/examples/metadata/provider_version_changed_example.md create mode 100644 specification/appendix/examples/metadata/removing_columns_example.md create mode 100644 specification/appendix/examples/metadata/schema_metadata_example.md create mode 100644 specification/appendix/examples/metadata/schema_metadata_reference_example.md create mode 100644 specification/metadata/schema/providerversion.md create mode 100644 supporting_content/metadata/schema_creation_scenarios.md diff --git a/specification/appendix/appendix.mdpp b/specification/appendix/appendix.mdpp index 510b27ceb..3f9ea0cbd 100644 --- a/specification/appendix/appendix.mdpp +++ b/specification/appendix/appendix.mdpp @@ -4,3 +4,4 @@ !INCLUDE "grouping_constructs_for_resources_and_or_services.md",1 !INCLUDE "origination_of_cost_data.md",1 +!INCLUDE "examples/examples.mdpp",1 diff --git a/specification/appendix/examples/examples.mdpp b/specification/appendix/examples/examples.mdpp new file mode 100644 index 000000000..edf59c82a --- /dev/null +++ b/specification/appendix/examples/examples.mdpp @@ -0,0 +1,5 @@ +# Examples + +*This section is non-normative.* + +!INCLUDE "metadata/metadata_examples.mdpp",1 diff --git a/specification/appendix/examples/metadata/adding_new_columns_example.md b/specification/appendix/examples/metadata/adding_new_columns_example.md new file mode 100644 index 000000000..ede72f5c8 --- /dev/null +++ b/specification/appendix/examples/metadata/adding_new_columns_example.md @@ -0,0 +1,78 @@ +# Adding New Columns + +## Scenario + +ACME has decided add additional columns to their FOCUS data export. The new columns are x_awesome_column1, x_awesome_column2, and x_awesome_column3. The provider creates a new schema object to represent the new schema, this schema object has a unique SchemaId. The subsequent data exports that use the new schema include the new schema's id as a reference to their corresponding schema object. + +## Supplied Metadata + +## Location for the new schema object + +`/FOCUS/metadata/schemas/schema-23456-abcde-23456-abcde-23456.json` + +## Content for the new schema object + +```json + { + "SchemaId": "23456-abcde-23456-abcde-23456", + "FocusVersion": "1.0", + "CreationDate": "2024-02-02T12:01:03.083z", + "ColumnDefinition": [ + { + "ColumnName": "BillingAccountId", + "DataType": "STRING", + "StringMaxLength": 64, + "StringEncoding": "UTF-8" + }, + { + "ColumnName": "BillingAccountName", + "DataType": "STRING", + "StringMaxLength": 64, + "StringEncoding": "UTF-8" + }, + { + "ColumnName": "ChargePeriodStart", + "DataType": "DATETIME" + }, + { + "ColumnName": "ChargePeriodEnd", + "DataType": "DATETIME" + }, + { + "ColumnName": "BilledCost", + "DataType": "DECIMAL", + "NumericPrecision": 20, + "NumberScale": 10 + }, + { + "ColumnName": "EffectiveCost", + "DataType": "DECIMAL", + "NumericPrecision": 20, + "NumberScale": 10 + }, + { + "ColumnName": "Tags", + "DataType": "JSON", + "ProviderTagPrefixes": ["awecorp", "ac"] + }, + { + "ColumnName": "x_awesome_column1", + "DataType": "STRING", + "StringMaxLength": 64, + "StringEncoding": "UTF-8" + }, + { + "ColumnName": "x_awesome_column2", + "DataType": "DATETIME" + }, + { + "ColumnName": "x_awesome_column3", + "DataType": "STRING", + "StringMaxLength": 64, + "StringEncoding": "UTF-8" + } + ] +} +``` + +For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](../schema_metadata_reference_example.md) diff --git a/specification/appendix/examples/metadata/changing_column_metadata_example.md b/specification/appendix/examples/metadata/changing_column_metadata_example.md new file mode 100644 index 000000000..85d65e9f9 --- /dev/null +++ b/specification/appendix/examples/metadata/changing_column_metadata_example.md @@ -0,0 +1,72 @@ +# Changing a Column's Metadata Example + +## Scenario + +ACME has decided to change the datatype of column x_awesome_column1 from a string to a number. ACME creates a new schema object with the modification to x_awesome_column2. + +## Supplied Metadata + +## Location for the new schema object + +`/FOCUS/metadata/schemas/schema-67891-abcde-67891-abcde-67891.json` + +## Content for the new schema object + +```json + { + "SchemaId": "67891-abcde-67891-abcde-67891", + "FocusVersion": "1.0", + "CreationDate": "2024-06-02T12:01:03.083z", + "ColumnDefinition": [ + { + "ColumnName": "BillingAccountId", + "DataType": "STRING", + "StringMaxLength": 64, + "StringEncoding": "UTF-8" + }, + { + "ColumnName": "BillingAccountName", + "DataType": "STRING", + "StringMaxLength": 64, + "StringEncoding": "UTF-8" + }, + { + "ColumnName": "ChargePeriodStart", + "DataType": "DATETIME" + }, + { + "ColumnName": "ChargePeriodEnd", + "DataType": "DATETIME" + }, + { + "ColumnName": "BilledCost", + "DataType": "DECIMAL", + "NumericPrecision": 20, + "NumberScale": 10 + }, + { + "ColumnName": "EffectiveCost", + "DataType": "DECIMAL", + "NumericPrecision": 20, + "NumberScale": 10 + }, + { + "ColumnName": "Tags", + "DataType": "JSON", + "ProviderTagPrefixes": ["acme", "ac"] + }, + { + "ColumnName": "x_awesome_column1", + "DataType": "DECIMAL", + "NumericPrecision": 20, + "NumberScale": 10 + }, + { + "ColumnName": "x_awesome_column2", + "DataType": "DATETIME" + } + ] +} +``` + +For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](schema_metadata_reference_example.md) diff --git a/specification/appendix/examples/metadata/correcting_schema_errors_example.md b/specification/appendix/examples/metadata/correcting_schema_errors_example.md new file mode 100644 index 000000000..16d166c3b --- /dev/null +++ b/specification/appendix/examples/metadata/correcting_schema_errors_example.md @@ -0,0 +1,72 @@ +# Provider has an error in their schema metadata + +## Scenario + +ACME has discovered that while their export includes the column x_awesome_column3, the schema metadata does not include this column. In this case, the provider fixes the metadata in existing the schema object and does not need to create a new schema object. Reference metadata remains the same. + +## Supplied Metadata + +## Location of the schema object + +`/FOCUS/metadata/schemas/schema-34567-abcde-34567-abcde-34567.json` + +## Content of the schema object + +```json + { + "SchemaId": "34567-abcde-34567-abcde-34567", + "FocusVersion": "1.0", + "CreationDate": "2024-03-02T12:01:03.083z", + "ColumnDefinition": [ + { + "ColumnName": "BillingAccountId", + "DataType": "STRING", + "StringMaxLength": 64, + "StringEncoding": "UTF-8" + }, + { + "ColumnName": "BillingAccountName", + "DataType": "STRING", + "StringMaxLength": 64, + "StringEncoding": "UTF-8" + }, + { + "ColumnName": "ChargePeriodStart", + "DataType": "DATETIME" + }, + { + "ColumnName": "ChargePeriodEnd", + "DataType": "DATETIME" + }, + { + "ColumnName": "BilledCost", + "DataType": "DECIMAL", + "NumericPrecision": 20, + "NumberScale": 10 + }, + { + "ColumnName": "EffectiveCost", + "DataType": "DECIMAL", + "NumericPrecision": 20, + "NumberScale": 10 + }, + { + "ColumnName": "Tags", + "DataType": "JSON", + "ProviderTagPrefixes": ["acme", "ac"] + }, + { + "ColumnName": "x_awesome_column1", + "DataType": "STRING", + "StringMaxLength": 64, + "StringEncoding": "UTF-8" + }, + { + "ColumnName": "x_awesome_column2", + "DataType": "STRING", + "StringMaxLength": 64, + "StringEncoding": "UTF-8" + } + ] +} +``` diff --git a/specification/appendix/examples/metadata/data_generator_example.md b/specification/appendix/examples/metadata/data_generator_example.md new file mode 100644 index 000000000..932e52bb4 --- /dev/null +++ b/specification/appendix/examples/metadata/data_generator_example.md @@ -0,0 +1,20 @@ +# Data Generator Metadata + +## Scenario + +Acme provides metadata about the data generator. They provide this via the Data Generator schema object. + +## Supplied Metadata + +## Location of Data Generator Metadata File + +`/FOCUS/metadata/data_generator.json` + +## Content of Data Generator Metadata File + +```json +{ + "DataGenerator": "Acme" +} +``` + diff --git a/specification/appendix/examples/metadata/focus_version_changed_example.md b/specification/appendix/examples/metadata/focus_version_changed_example.md new file mode 100644 index 000000000..31a28b8ce --- /dev/null +++ b/specification/appendix/examples/metadata/focus_version_changed_example.md @@ -0,0 +1,72 @@ +# Provider has an error in their schema metadata + +## Scenario + +ACME's previous exports used Focus Version 1.0. They are now going to adopt Focus Version 1.1. It is required that they create a new schema metadata object when using a new FOCUS version regardless of schema changes. In this example, the FOCUS new version adoption doesn't include columns changes. This is to illustrate that FOCUS Version changes are independent of column changes, however, this scenario is unlikely. + +## Supplied Metadata + +## Location of the new schema object + +`/FOCUS/metadata/schemas/schema-45678-abcde-45678-abcde-45678.json` + +## Content of the schema object + +```json + { + "SchemaId": "45678-abcde-45678-abcde-45678", + "FocusVersion": "1.1", + "CreationDate": "2024-04-02T12:01:03.083z", + "ColumnDefinition": [ + { + "ColumnName": "BillingAccountId", + "DataType": "STRING", + "StringMaxLength": 64, + "StringEncoding": "UTF-8" + }, + { + "ColumnName": "BillingAccountName", + "DataType": "STRING", + "StringMaxLength": 64, + "StringEncoding": "UTF-8" + }, + { + "ColumnName": "ChargePeriodStart", + "DataType": "DATETIME" + }, + { + "ColumnName": "ChargePeriodEnd", + "DataType": "DATETIME" + }, + { + "ColumnName": "BilledCost", + "DataType": "DECIMAL", + "NumericPrecision": 20, + "NumberScale": 10 + }, + { + "ColumnName": "EffectiveCost", + "DataType": "DECIMAL", + "NumericPrecision": 20, + "NumberScale": 10 + }, + { + "ColumnName": "Tags", + "DataType": "JSON", + "ProviderTagPrefixes": ["acme", "ac"] + }, + { + "ColumnName": "x_awesome_column1", + "DataType": "STRING", + "StringMaxLength": 64, + "StringEncoding": "UTF-8" + }, + { + "ColumnName": "x_awesome_column2", + "DataType": "DATETIME" + } + ] +} +``` + +For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](schema_metadata_reference_example.md) diff --git a/specification/appendix/examples/metadata/focus_version_changed_with_provider_version_used_example.md b/specification/appendix/examples/metadata/focus_version_changed_with_provider_version_used_example.md new file mode 100644 index 000000000..bf166cfa3 --- /dev/null +++ b/specification/appendix/examples/metadata/focus_version_changed_with_provider_version_used_example.md @@ -0,0 +1,140 @@ +# FOCUS Version Changed by Provider Using Provider Version + +## Scenario + +ACME uses Provider Version, and their previous exports used FOCUS Version 1.0. Their current Provider Version is 2.2. They are now going to adopt FOCUS Version 1.1. Because it is required that they update their Provider Version when using a new FOCUS Version, they create a new schema object designating that both have changed. In this example, the adoption of the new FOCUS Version doesn't include additional columns. This is to illustrate that Provider Version changes are independent of column changes; however, this scenario is unlikely. + +The provider creates a new schema object to represent the new schema. The provider includes both the new FOCUS Version and Provider Version in the schema object. + +## Supplied Metadata + +## Location of the previous schema object + +`/FOCUS/metadata/schemas/schema-34567-abcde-34567-abcde-34567.json` + +## Content of the previous schema object + +```json + { + "SchemaId": "34567-abcde-34567-abcde-34567", + "FocusVersion": "1.1", + "ProviderVersion": "2.2", + "CreationDate": "2024-04-02T12:01:03.083z", + "ColumnDefinition": [ + { + "ColumnName": "BillingAccountId", + "DataType": "STRING", + "StringMaxLength": 64, + "StringEncoding": "UTF-8" + }, + { + "ColumnName": "BillingAccountName", + "DataType": "STRING", + "StringMaxLength": 64, + "StringEncoding": "UTF-8" + }, + { + "ColumnName": "ChargePeriodStart", + "DataType": "DATETIME" + }, + { + "ColumnName": "ChargePeriodEnd", + "DataType": "DATETIME" + }, + { + "ColumnName": "BilledCost", + "DataType": "DECIMAL", + "NumericPrecision": 20, + "NumberScale": 10 + }, + { + "ColumnName": "EffectiveCost", + "DataType": "DECIMAL", + "NumericPrecision": 20, + "NumberScale": 10 + }, + { + "ColumnName": "Tags", + "DataType": "JSON", + "ProviderTagPrefixes": ["acme", "ac"] + }, + { + "ColumnName": "x_awesome_column1", + "DataType": "STRING", + "StringMaxLength": 64, + "StringEncoding": "UTF-8" + }, + { + "ColumnName": "x_awesome_column2", + "DataType": "DATETIME" + } + ] +} +``` + +## Location of the new schema object + +`/FOCUS/metadata/schemas/schema-45678-abcde-45678-abcde-45678.json` + +## Content of the new schema object + +```json + { + "SchemaId": "45678-abcde-45678-abcde-45678", + "FocusVersion": "1.1", + "ProviderVersion": "2.3", + "name": "New Columns", + "CreationDate": "2024-04-02T12:01:03.083z", + "ColumnDefinition": [ + { + "ColumnName": "BillingAccountId", + "DataType": "STRING", + "StringMaxLength": 64, + "StringEncoding": "UTF-8" + }, + { + "ColumnName": "BillingAccountName", + "DataType": "STRING", + "StringMaxLength": 64, + "StringEncoding": "UTF-8" + }, + { + "ColumnName": "ChargePeriodStart", + "DataType": "DATETIME" + }, + { + "ColumnName": "ChargePeriodEnd", + "DataType": "DATETIME" + }, + { + "ColumnName": "BilledCost", + "DataType": "DECIMAL", + "NumericPrecision": 20, + "NumberScale": 10 + }, + { + "ColumnName": "EffectiveCost", + "DataType": "DECIMAL", + "NumericPrecision": 20, + "NumberScale": 10 + }, + { + "ColumnName": "Tags", + "DataType": "JSON", + "ProviderTagPrefixes": ["acme", "ac"] + }, + { + "ColumnName": "x_awesome_column1", + "DataType": "STRING", + "StringMaxLength": 64, + "StringEncoding": "UTF-8" + }, + { + "ColumnName": "x_awesome_column2", + "DataType": "DATETIME" + } + ] +} +``` + +For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](schema_metadata_reference_example.md) diff --git a/specification/appendix/examples/metadata/metadata_examples.mdpp b/specification/appendix/examples/metadata/metadata_examples.mdpp new file mode 100644 index 000000000..58d75735d --- /dev/null +++ b/specification/appendix/examples/metadata/metadata_examples.mdpp @@ -0,0 +1,24 @@ +# Metadata Examples + +The following is an example metadata JSON structure provided by a hypothetical FOCUS data provider called ACME. This example illustrates an example of how a provider can supply the required reference between the FOCUS data and the schema metadata. Provider implementations will vary on how the metadata is stored and retrieved; however, the provider's chosen metadata delivery approach should be able to support the structure represented in this example. + +## Scenario + +In this example, the provider supports delivery of FOCUS data via file export to a data storage system. The provider delivers data every 12 hours. + +## Example Data Structure + +* export root location: `/FOCUS` +* metadata location: `/FOCUS/metadata` +* focus data location: `/FOCUS/data` + +!INCLUDE "data_generator_example.md",1 +!INCLUDE "schema_metadata_example.md",1 +!INCLUDE "schema_metadata_reference_example.md",1 +!INCLUDE "adding_new_columns_example.md",1 +!INCLUDE "removing_columns_example.md",1 +!INCLUDE "changing_a_columns_metadata_example.md", +!INCLUDE "correcting_schema_error_example.md",1 +!INCLUDE "focus_version_changed_example.md",1 +!INCLUDE "focus_version_changed_with_provider_version_example.md",1 +!INCLUDE "provider_version_changed.md",1 diff --git a/specification/appendix/examples/metadata/provider_version_changed_example.md b/specification/appendix/examples/metadata/provider_version_changed_example.md new file mode 100644 index 000000000..530e56ca7 --- /dev/null +++ b/specification/appendix/examples/metadata/provider_version_changed_example.md @@ -0,0 +1,76 @@ +# FOCUS Version Changed by Provider Using Provider Version + +## Scenario + +ACME uses provider version, and they made a change to their approach to create FOCUS data that does not adopt a new FOCUS Version, nor make a change the included columns but does impact values in the data. This is to illustrate that Provider Version changes are independent of column changes, however provider version changes may include column changes. + +The provider creates a new schema object to represent the new schema. The provider includes both the new FOCUS Version and Provider Version in the schema object. + +## Supplied Metadata + +## Location of the new schema object + + +`/FOCUS/metadata/schemas/schema-56789-abcde-56789-abcde-56789.json` + +## Content of the new schema object + +```json + { + "SchemaId": "56789-abcde-56789-abcde-56789", + "FocusVersion": "1.1", + "ProviderVersion": "2.4", + "CreationDate": "2024-05-02T12:01:03.083z", + "ColumnDefinition": [ + { + "ColumnName": "BillingAccountId", + "DataType": "STRING", + "StringMaxLength": 64, + "StringEncoding": "UTF-8" + }, + { + "ColumnName": "BillingAccountName", + "DataType": "STRING", + "StringMaxLength": 64, + "StringEncoding": "UTF-8" + }, + { + "ColumnName": "ChargePeriodStart", + "DataType": "DATETIME" + }, + { + "ColumnName": "ChargePeriodEnd", + "DataType": "DATETIME" + }, + { + "ColumnName": "BilledCost", + "DataType": "DECIMAL", + "NumericPrecision": 20, + "NumberScale": 10 + }, + { + "ColumnName": "EffectiveCost", + "DataType": "DECIMAL", + "NumericPrecision": 20, + "NumberScale": 10 + }, + { + "ColumnName": "Tags", + "DataType": "JSON", + "ProviderTagPrefixes": ["acme", "ac"] + }, + { + "ColumnName": "x_awesome_column1", + "DataType": "STRING", + "StringMaxLength": 64, + "StringEncoding": "UTF-8" + }, + { + "ColumnName": "x_awesome_column2", + "DataType": "DATETIME" + } + ] +} +``` + +For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](schema_metadata_reference_example.md) diff --git a/specification/appendix/examples/metadata/removing_columns_example.md b/specification/appendix/examples/metadata/removing_columns_example.md new file mode 100644 index 000000000..b9f47e31e --- /dev/null +++ b/specification/appendix/examples/metadata/removing_columns_example.md @@ -0,0 +1,72 @@ +# Removing Columns + +## Scenario + +ACME has decided to remove columns from their FOCUS data export. The column removed is x_awesome_column3. The provider creates a new schema object to represent the new schema, this schema object has a unique SchemaId. + +## Supplied Metadata + +## Location for the new schema object + +`/FOCUS/metadata/schemas/schema-34567-abcde-34567-abcde-34567.json` + +## Content for the new schema object + +```json + { + "SchemaId": "34567-abcde-34567-abcde-34567", + "FocusVersion": "1.0", + "CreationDate": "2024-03-02T12:01:03.083z", + "ColumnDefinition": [ + { + "ColumnName": "BillingAccountId", + "DataType": "STRING", + "StringMaxLength": 64, + "StringEncoding": "UTF-8" + }, + { + "ColumnName": "BillingAccountName", + "DataType": "STRING", + "StringMaxLength": 64, + "StringEncoding": "UTF-8" + }, + { + "ColumnName": "ChargePeriodStart", + "DataType": "DATETIME" + }, + { + "ColumnName": "ChargePeriodEnd", + "DataType": "DATETIME" + }, + { + "ColumnName": "BilledCost", + "DataType": "DECIMAL", + "NumericPrecision": 20, + "NumberScale": 10 + }, + { + "ColumnName": "EffectiveCost", + "DataType": "DECIMAL", + "NumericPrecision": 20, + "NumberScale": 10 + }, + { + "ColumnName": "Tags", + "DataType": "JSON", + "ProviderTagPrefixes": ["acme", "ac"] + }, + { + "ColumnName": "x_awesome_column1", + "DataType": "STRING", + "StringMaxLength": 64, + "StringEncoding": "UTF-8" + }, + { + "ColumnName": "x_awesome_column2", + "DataType": "DATETIME" + } + ] +} +``` + +For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](schema_metadata_reference_example.md) diff --git a/specification/appendix/examples/metadata/schema_metadata_example.md b/specification/appendix/examples/metadata/schema_metadata_example.md new file mode 100644 index 000000000..6a52bda73 --- /dev/null +++ b/specification/appendix/examples/metadata/schema_metadata_example.md @@ -0,0 +1,61 @@ +# Schema Metadata Example + +## Scenario + +ACME has only provided one schema for their provided FOCUS data. ACME provides a directory of schemas and each schema is a single file. Acme's provides a file representing the schema for the data they provide. + +## Supplied Metadata + +## Location of the schema object + +`/FOCUS/metadata/schemas/schema-1234-abcde-12345-abcde-12345.json` + +## Content of the schema object + +```json +{ + "SchemaId": "1234-abcde-12345-abcde-12345", + "FocusVersion": "1.0", + "CreationDate": "2024-01-01T12:01:03.083z", + "ColumnDefinition": [ + { + "ColumnName": "BillingAccountId", + "DataType": "STRING", + "StringMaxLength": 64, + "StringEncoding": "UTF-8" + }, + { + "ColumnName": "BillingAccountName", + "DataType": "STRING", + "StringMaxLength": 64, + "StringEncoding": "UTF-8" + }, + { + "ColumnName": "ChargePeriodStart", + "DataType": "DATETIME" + }, + { + "ColumnName": "ChargePeriodEnd", + "DataType": "DATETIME" + }, + { + "ColumnName": "BilledCost", + "DataType": "DECIMAL", + "NumericPrecision": 20, + "NumberScale": 10 + }, + { + "ColumnName": "EffectiveCost", + "DataType": "DECIMAL", + "NumericPrecision": 20, + "NumberScale": 10 + }, + { + "ColumnName": "Tags", + "DataType": "JSON", + "ProviderTagPrefixes": ["acme", "ac"] + } + ] +} +``` + diff --git a/specification/appendix/examples/metadata/schema_metadata_reference_example.md b/specification/appendix/examples/metadata/schema_metadata_reference_example.md new file mode 100644 index 000000000..9edab82c1 --- /dev/null +++ b/specification/appendix/examples/metadata/schema_metadata_reference_example.md @@ -0,0 +1,78 @@ +# Schema Metadata to FOCUS Data Reference + +## Scenario + +ACME makes a change to the schema of their data exports. For each FOCUS data export, ACME includes a metadata reference to the schema object. Because multiple files are provided, Acme has elected to include a metadata file that includes the focus schema reference that applies to the data export files. They therefore include the new schema id in their export metadata file. + +## Supplied Metadata + +## Location of the existing schema metadata reference file + +`/FOCUS/data/export1-metadata.json` + +## Content for the existing export metadata object + +```json +{ + "SchemaId":"1234-abcde-12345-abcde-12345", + "data_location": + [ + { + "filepath": "/FOCUS/data/export1/export1-part1.csv", + "total_bytes": 9010387, + "total_rows": 4450 + }, + { + "filepath": "/FOCUS/data/export1/export1-part2.csv", + "total_bytes": 9010387, + "total_rows": 4450 + }, + { + "filepath": "/FOCUS/data/export1/export1-part3.csv", + "total_bytes": 9010387, + "total_rows": 4450 + }, + { + "filepath": "/FOCUS/data/export1/export1-part4.csv", + "total_bytes": 9010387, + "total_rows": 4450 + } + ] +} +``` + +## Location for the new export metadata object + +`/FOCUS/data/export2-metadata.json` + +## Content for the new export metadata object + +```json +{ + "SchemaId":"23456-abcde-23456-abcde-23456", + "data_location": + [ + { + "filepath": "/FOCUS/data/export2/export2-part1.csv", + "total_bytes": 9010387, + "total_rows": 4450 + }, + { + "filepath": "/FOCUS/data/export2/export2-part2.csv", + "total_bytes": 9010387, + "total_rows": 4450 + }, + { + "filepath": "/FOCUS/data/export2/export2-part3.csv", + "total_bytes": 9010387, + "total_rows": 4450 + }, + { + "filepath": "/FOCUS/data/export2/export2-part4.csv", + "total_bytes": 9010387, + "total_rows": 4450 + } + ] +} +``` + diff --git a/specification/metadata/data_generator/data_generator.mdpp b/specification/metadata/data_generator/data_generator.mdpp index 80b36aa5c..2526c9bc2 100644 --- a/specification/metadata/data_generator/data_generator.mdpp +++ b/specification/metadata/data_generator/data_generator.mdpp @@ -2,4 +2,12 @@ The FOCUS metadata about the generator of the FOCUS data. +## Requirements + +The FOCUS Data Generator metadata MUST be provided. This metadata MUST be of type Object and MUST NOT contain null values. + +## Schema Example + +For an example of the FOCUS Data Generator metadata please refer to: [Data Generator Example](#data_generator_example) + !INCLUDE "datagenerator.md",1 diff --git a/specification/metadata/data_generator/datagenerator.md b/specification/metadata/data_generator/datagenerator.md index a731c5999..abc636b46 100644 --- a/specification/metadata/data_generator/datagenerator.md +++ b/specification/metadata/data_generator/datagenerator.md @@ -1,8 +1,8 @@ # Data Generator -Human readable name of the entity that is generating the data. +Human-readable name of the entity that is generating the data. -The DataGenerator MUST be provided in the metadata. DataGenerator MUST be of type String and MUST NOT contain null values. The DataGenerator SHOULD be easily associated with the provider who generated the FOCUS dataset. +The DataGenerator MUST be provided in the metadata. DataGenerator MUST be of type String and MUST NOT be null. The DataGenerator SHOULD be easily associated with the provider who generated the FOCUS dataset. ## Metadata ID @@ -12,6 +12,15 @@ DataGenerator Data Generator +## Content constraints + +| Constraint | Value | +|:----------------|:-----------------| +| Feature level | Mandatory | +| Allows nulls | False | +| Data type | String | +| Value format | \ | + ## Introduced (version) 1.0 diff --git a/specification/metadata/metadata.mdpp b/specification/metadata/metadata.mdpp index 4b1b22fe0..46a776168 100644 --- a/specification/metadata/metadata.mdpp +++ b/specification/metadata/metadata.mdpp @@ -1,6 +1,8 @@ # Metadata -The FOCUS specification defines a metadata structure that is to be supplied by data providers to facilitate practitioners use of FOCUS data. This meta data includes general information about the data generator and the schema of the FOCUS dataset. FOCUS Metadata SHOULD be provided in a format that is accessible programmatically, such as: a file, website, api, table. +The FOCUS specification defines a metadata structure to be supplied by data providers to facilitate practitioners' use of FOCUS data. This metadata includes general information about the data generator and the schema of the FOCUS dataset. + +FOCUS Metadata SHOULD be provided in a format that is accessible programmatically, such as a file, website, API, or table. Providers SHOULD provide documentation on their implementation of the FOCUS metadata. !INCLUDE "data_generator/data_generator.mdpp",1 -!INCLUDE "schema/schema.mdpp",1 +!INCLUDE "schema/schema.mdpp",1 \ No newline at end of file diff --git a/specification/metadata/schema/column_definition/column_definition.mdpp b/specification/metadata/schema/column_definition/column_definition.mdpp index 75971504e..18a2f8490 100644 --- a/specification/metadata/schema/column_definition/column_definition.mdpp +++ b/specification/metadata/schema/column_definition/column_definition.mdpp @@ -2,6 +2,10 @@ The FOCUS metadata schema column definition provides a list of the columns present in the FOCUS dataset along with metadata about the columns. +## Requirements + +This metadata MUST be present in the FOCUS metadata schema. This metadata MUST be of type Object and MUST NOT contain null values. + !INCLUDE "columnname.md",1 !INCLUDE "datatype.md",1 !INCLUDE "numericprecision.md",1 diff --git a/specification/metadata/schema/column_definition/columnname.md b/specification/metadata/schema/column_definition/columnname.md index cc9ff728b..bd6b40f96 100644 --- a/specification/metadata/schema/column_definition/columnname.md +++ b/specification/metadata/schema/column_definition/columnname.md @@ -12,6 +12,15 @@ ColumnName Column Name +## Content constraints + +| Constraint | Value | +|:----------------|:-----------------| +| Feature level | Mandatory | +| Allows nulls | False | +| Data type | String | +| Value format | \ | + ## Introduced (version) 1.0 diff --git a/specification/metadata/schema/column_definition/datatype.md b/specification/metadata/schema/column_definition/datatype.md index bd099443d..8a33adbca 100644 --- a/specification/metadata/schema/column_definition/datatype.md +++ b/specification/metadata/schema/column_definition/datatype.md @@ -12,6 +12,15 @@ DataType Data Type +## Content constraints + +| Constraint | Value | +|:----------------|:-----------------| +| Feature level | Mandatory | +| Allows nulls | False | +| Data type | String | +| Value format | \ | + ## Introduced (version) 1.0 diff --git a/specification/metadata/schema/column_definition/numberscale.md b/specification/metadata/schema/column_definition/numberscale.md index 4602e7058..e45bdbd1b 100644 --- a/specification/metadata/schema/column_definition/numberscale.md +++ b/specification/metadata/schema/column_definition/numberscale.md @@ -12,6 +12,15 @@ NumberScale Number Scale +## Content constraints + +| Constraint | Value | +|:--------------|:---------------------------------| +| Feature level | Conditional | +| Allows nulls | False | +| Data type | Integer | +| Value format | [Numeric Format](#numericformat) | + ## Introduced (version) 1.0 \ No newline at end of file diff --git a/specification/metadata/schema/column_definition/numericprecision.md b/specification/metadata/schema/column_definition/numericprecision.md index 1ac35d95c..999c73c46 100644 --- a/specification/metadata/schema/column_definition/numericprecision.md +++ b/specification/metadata/schema/column_definition/numericprecision.md @@ -12,6 +12,15 @@ NumericPrecision Numeric Precision +## Content constraints + +| Constraint | Value | +|:--------------|:---------------------------------| +| Feature level | Conditional | +| Allows nulls | False | +| Data type | Integer | +| Value format | [Numeric Format](#numericformat) | + ## Introduced (version) 1.0 diff --git a/specification/metadata/schema/column_definition/providertagprefixes.md b/specification/metadata/schema/column_definition/providertagprefixes.md index d6267ffae..ca8ddb4b6 100644 --- a/specification/metadata/schema/column_definition/providertagprefixes.md +++ b/specification/metadata/schema/column_definition/providertagprefixes.md @@ -12,6 +12,15 @@ ProviderTagPrefixes Provider Tag Prefixes +## Content constraints + +| Constraint | Value | +|:--------------|:------------------------------------| +| Feature level | Conditional | +| Allows nulls | False | +| Data type | Array | +| Value format | STRING datatype values in the array | + ## Introduced (version) 1.0 diff --git a/specification/metadata/schema/column_definition/stringencoding.md b/specification/metadata/schema/column_definition/stringencoding.md index cb9f870a1..49f7fba22 100644 --- a/specification/metadata/schema/column_definition/stringencoding.md +++ b/specification/metadata/schema/column_definition/stringencoding.md @@ -12,6 +12,15 @@ StringEncoding StringEncoding +## Content constraints + +| Constraint | Value | +|:----------------|:-----------------| +| Feature level | Conditional | +| Allows nulls | False | +| Data type | String | +| Value format | \ | + ## Introduced (version) 1.0 diff --git a/specification/metadata/schema/column_definition/stringmaxlength.md b/specification/metadata/schema/column_definition/stringmaxlength.md index 69a74e3e0..4a0299995 100644 --- a/specification/metadata/schema/column_definition/stringmaxlength.md +++ b/specification/metadata/schema/column_definition/stringmaxlength.md @@ -12,6 +12,15 @@ StringMaxLength String Max Length +## Content constraints + +| Constraint | Value | +|:--------------|:---------------------------------| +| Feature level | Conditional | +| Allows nulls | False | +| Data type | Integer | +| Value format | [Numeric Format](#numericformat) | + ## Introduced (version) 1.0 diff --git a/specification/metadata/schema/creationdate.md b/specification/metadata/schema/creationdate.md index 6c5ed6bc1..77cbc92fd 100644 --- a/specification/metadata/schema/creationdate.md +++ b/specification/metadata/schema/creationdate.md @@ -12,6 +12,15 @@ CreationDate Creation Date +## Content constraints + +| Constraint | Value | +|:--------------|:------------------------------------------| +| Feature level | Mandatory | +| Allows nulls | False | +| Data type | Date/Time | +| Value format | [Date/Time Format](#date/timeformat) | + ## Introduced (version) 1.0 diff --git a/specification/metadata/schema/focusversion.md b/specification/metadata/schema/focusversion.md index c650665bd..323b54428 100644 --- a/specification/metadata/schema/focusversion.md +++ b/specification/metadata/schema/focusversion.md @@ -2,7 +2,7 @@ The version of FOCUS utilized for building the dataset. -The FocusVersion MUST be provided in the metadata. FocusVersion MUST be of type String and MUST NOT contain null values. FOCUSVersion MUST match one of the published versions of the FOCUS specification. FocusVersion MUST match the version of the FOCUS specification that the FOCUS dataset conforms to. +The FocusVersion MUST be provided in the metadata. FocusVersion MUST be of type String and MUST NOT contain null values. FocusVersion MUST match one of the published versions of the FOCUS specification. FocusVersion MUST match the version of the FOCUS specification that the FOCUS dataset conforms to. ## Metadata ID @@ -12,6 +12,15 @@ FocusVersion FOCUS Version +## Content constraints + +| Constraint | Value | +|:--------------|:-----------------------------------------| +| Feature level | Mandatory | +| Allows nulls | False | +| Data type | STRING | +| Value format | Must align with a published FocusVersion | + ## Introduced (version) 1.0 diff --git a/specification/metadata/schema/providerversion.md b/specification/metadata/schema/providerversion.md new file mode 100644 index 000000000..bcf3ebe6d --- /dev/null +++ b/specification/metadata/schema/providerversion.md @@ -0,0 +1,26 @@ +# Provider Version + +The ProviderVersion MAY be supplied to declare the version of logic by which the FOCUS dataset was generated and is separate from FOCUS Version. ProviderVersion allows for the provider to specify changes that may not result in a structural change in the data. It is suggested that the provider version use a versioning approach such as [SemVer](https://semver.org) version. + +ProviderVersion MUST be of type String and MUST NOT contain null values. If FocusVersion is changed a new ProviderVersion MUST be also changed. The provider MUST document what changes are present in the ProviderVersion. + +## Metadata ID + +ProviderVersion + +## Metadata Name + +Provider Version + +## Content constraints + +| Constraint | Value | +|:--------------|:-----------------| +| Feature level | Optional | +| Allows nulls | False | +| Data type | STRING | +| Value format | \ | + +## Introduced (version) + +1.1 diff --git a/specification/metadata/schema/schema.mdpp b/specification/metadata/schema/schema.mdpp index b27448e13..7d211016c 100644 --- a/specification/metadata/schema/schema.mdpp +++ b/specification/metadata/schema/schema.mdpp @@ -1,8 +1,38 @@ # Schema -Each FOCUS dataset must have a metadata about the schema associated with it. The schema metadata provides information about the structure of the data provided. +The schema metadata object and its contents provides information about the structure of the data provided. + +## Requirements + +### Reference to FOCUS Data + +FOCUS data artifacts, whether they are data files, data streams, or data tables, MUST provide a clear reference to the schema of the data. This reference MUST be retrievable without inspection of the contents of the FOCUS data within the data artifact. For some delivery mechanisms such as database tables, the provider may rely on the schema functionality of the providing system. + +It is recommended that the schema reference be provided as an external reference rather than included in full as metadata accompanying the data artifact. This allows for easier understanding of when changes to the schema of the FOCUS datasets occurs. + +### Schema Metadata Creation + +Should the provider change the structure of the supplied FOCUS data artifact, a new schema metadata object MUST be supplied. +These scenarios include, but are not limited to: + +* [Adding a new column](#adding_new_columns_example) +* [Removing a column](#removing_columns_example) +* [Renaming a column](#renaming_columns_example) +* [Changing column metadata](#changing_column_metadata_example) +* [FOCUS Version is changed](#focus_version_change_example) +* [Provider Version is changed](#provider_version_change_example) +* [Correcting schema metadata errors](#correcting_schema_metadata_errors) + +### Schema Metadata Updates + +Should there be an error where the schema metadata object does not match the schema of the FOCUS data artifact, the provider MUST update the schema metadata object to match the schema of the FOCUS data artifact. This is to ensure that the schema metadata object is always accurate. + +## Schema Example + +For an example of the FOCUS schema metadata please refer to: [Schema Metadata Example](#schema-metadata-examples) !INCLUDE "schemaid.md",1 !INCLUDE "creationdate.md",1 !INCLUDE "focusversion.md",1 +!INCLUDE "providerversion.md", !INCLUDE "column_definition/column_definition.mdpp",1 diff --git a/specification/metadata/schema/schemaid.md b/specification/metadata/schema/schemaid.md index d55872250..c1cf64388 100644 --- a/specification/metadata/schema/schemaid.md +++ b/specification/metadata/schema/schemaid.md @@ -2,7 +2,7 @@ The Schema ID provides the reference item to associate which Schema was used for the generation of a FOCUS Dataset. -The SchemaId MUST be present in the metadata. The SchemaId MUST be of String. It is RECOMMENDED for SchemaId to be a Universally Unique Identifier (UUID) or [SemVer](https://semver.org) version. +The SchemaId MUST be present in the metadata. The SchemaId MUST be of String. It is RECOMMENDED for SchemaId to be a Globally Unique Identifier (GUID). ## Metadata ID @@ -12,6 +12,15 @@ SchemaId Schema ID +## Content constraints + +| Constraint | Value | +|:--------------|:----------------------| +| Feature level | Mandatory | +| Allows nulls | False | +| Data type | STRING | +| Value format | Recommend GUID String | + ## Introduced (version) 1.0 diff --git a/supporting_content/metadata/schema_creation_scenarios.md b/supporting_content/metadata/schema_creation_scenarios.md new file mode 100644 index 000000000..bbe6a39de --- /dev/null +++ b/supporting_content/metadata/schema_creation_scenarios.md @@ -0,0 +1,13 @@ +# Scheme Creation Scenarios + +## The following is a list of scenarios and their schema update requirements + + +| Scenario | Requires New Schema object | Requires Change in Provider Version | Requires Change FOCUS Version | +|:---------------------------------------------------------------------------------------------------------|:----------------------------|:------------------------------------|:-------------------------------| +| Provider uses a new focus version when they supply a provider version | Y | | Y |N | +| Provider is changing the way they generate the data that doesn't affect the focus version or the columns | Y | Y | N | +| Addition of Column | Y | N | N | +| Removal of Columns | Y | N | N | +| Change of Focus Version | Y | Y| Y| +| Correction of schema metadata that is not correct | N | N | N | \ No newline at end of file From e9f07d0bfcc0bc214dc5980d4181e8419f0b08a4 Mon Sep 17 00:00:00 2001 From: Shawn Alpay <77511110+salpaysenturus@users.noreply.github.com> Date: Thu, 19 Sep 2024 17:09:00 -0700 Subject: [PATCH 30/52] FOCUS #404: Service Subcategory (#519) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduction of column _ServiceSubcategory_ underneath the existing column _ServiceCategory_ to capture finer grouping detail for Services. **Lead Maintainer**: Shawn Alpay, @salpaysenturus ### Documents: * [Categorization principles](https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/blob/working_draft/supporting_content/columns/servicecategory.md) * **Slack channel**: “[# tf-service-categorization](https://f2-focus.slack.com/archives/C07A21GKUCD)” * **Folder**:[ #404-subcategories](https://drive.google.com/drive/u/0/folders/134b1Alk5zDHy77iGh3Sv2a_J7zext-LP) * **Presentation**:[ Service Subcategories](https://docs.google.com/presentation/d/1kzndJctjrXROoSodF88ehaMWJXt8Nl9EkuohVCv1ilI/edit#slide=id.p) * **Spreadsheet**: [24.06.27 Service Subcategories](https://docs.google.com/spreadsheets/d/1aYq79sWp8TK4zbcSKUb-gRIBei3fERVwAgDJ5ezZf1w/edit?gid=0#gid=0) * **PR**: [#519 ](https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/pull/519)#404: Service Subcategory * **Approval deadline**: ~Aug 29~, Sep 5, --------- Co-authored-by: Udam Dewaraja Co-authored-by: Michael Flanakin Co-authored-by: Joaquin --- specification/columns/columns.mdpp | 1 + specification/columns/servicesubcategory.md | 121 ++++++++++ .../columns/servicesubcategory.md | 210 ++++++++++++++++++ 3 files changed, 332 insertions(+) create mode 100644 specification/columns/servicesubcategory.md create mode 100644 supporting_content/columns/servicesubcategory.md diff --git a/specification/columns/columns.mdpp b/specification/columns/columns.mdpp index 7b1e126a6..aac55c69a 100644 --- a/specification/columns/columns.mdpp +++ b/specification/columns/columns.mdpp @@ -44,6 +44,7 @@ The FOCUS specification defines a group of columns that provide qualitative valu !INCLUDE "resourcetype.md",1 !INCLUDE "servicecategory.md",1 !INCLUDE "servicename.md",1 +!INCLUDE "servicesubcategory.md",1 !INCLUDE "skuid.md",1 !INCLUDE "skupricedetails.md",1 !INCLUDE "skupriceid.md",1 diff --git a/specification/columns/servicesubcategory.md b/specification/columns/servicesubcategory.md new file mode 100644 index 000000000..82548de45 --- /dev/null +++ b/specification/columns/servicesubcategory.md @@ -0,0 +1,121 @@ +# Service Subcategory + +The Service Subcategory is a secondary classification of the Service Category for a [*service*](#glossary:service) based on its core function. The Service Subcategory (in conjunction with the Service Category) is commonly used for scenarios like analyzing spend and usage for specific workload types across providers and tracking the migration of workloads across fundamentally different architectures. + +* The ServiceSubcategory column MUST be present in a FOCUS dataset and MUST NOT be null. +* This column is of type String and MUST be one of the allowed values. +* Each Service Subcategory value MUST have one and only one Service Category parent. +* Though a given *service* can have multiple purposes, each *service* SHOULD have one and only one Subcategory that best aligns with its primary purpose. + +## Column ID + +ServiceSubcategory + +## Display Name + +Service Subcategory + +## Description + +Secondary classification of the Service Category for a *service* based on its core function. + +## Content Constraints + +| Constraint | Value | +| :-------------- | :------------- | +| Column type | Dimension | +| Feature level | Optional | +| Allows nulls | False | +| Data type | String | +| Value format | Allowed Values | + +Allowed values: + +| Service Category | Service Subcategory | Service Subcategory Description | +| ------------------------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------- | +| AI and Machine Learning | AI Platforms | Unified solution that combines artificial intelligence and machine learning technologies. | +| AI and Machine Learning | Bots | Automated performance of tasks such as customer service, data collection, and content moderation. | +| AI and Machine Learning | Generative AI | Creation of content like text, images, and music by learning patterns from existing data. | +| AI and Machine Learning | Machine Learning | Creation, training, and deployment of statistical algorithms that learn from and perform tasks based on data. | +| AI and Machine Learning | Natural Language Processing | Generation of human language, handling tasks like translation, sentiment analysis, and text summarization. | +| AI and Machine Learning | Other (AI and Machine Learning) | AI and Machine Learning services that do not fall into one of the defined subcategories. | +| Analytics | Analytics Platforms | Unified solution that combines technologies across the entire analytics lifecycle. | +| Analytics | Business Intelligence | Semantic models, dashboards, reports, and data visualizations to track performance and identify trends. | +| Analytics | Data Processing | Integration and transformation tasks to prepare data for analysis. | +| Analytics | Search | Discovery of information by indexing and retrieving data from various sources. | +| Analytics | Streaming Analytics | Real-time data stream processes to detect patterns, trends, and anomalies as they occur. | +| Analytics | Other (Analytics) | Analytics services that do not fall into one of the defined subcategories. | +| Business Applications | Productivity and Collaboration | Tools that facilitate individuals managing tasks and working together. | +| Business Applications | Other (Business Applications) | Business Applications services that do not fall into one of the defined subcategories. | +| Compute | Containers | Management and orchestration of containerized compute platforms. | +| Compute | End User Computing | Virtualized desktop infrastructure and device / endpoint management. | +| Compute | Quantum Compute | Resources and simulators that leverage the principles of quantum mechanics. | +| Compute | Serverless Compute | Enablement of compute capabilities without provisioning or managing servers. | +| Compute | Virtual Machines | Computing environments ranging from hosts with abstracted operating systems to bare-metal servers. | +| Compute | Other (Compute) | Compute services that do not fall into one of the defined subcategories. | +| Databases | Caching | Low-latency and high-throughput access to frequently accessed data. | +| Databases | Data Warehouses | Big data storage and querying capabilities. | +| Databases | Ledger Databases | Immutable and transparent databases to record tamper-proof and cryptographically secure transactions. | +| Databases | NoSQL Databases | Unstructured or semi-structured data storage and querying capabilities. | +| Databases | Relational Databases | Structured data storage and querying capabilities. | +| Databases | Time Series Databases | Time-stamped data storage and querying capabilities. | +| Databases | Other (Databases) | Database services that do not fall into one of the defined subcategories. | +| Developer Tools | Developer Platforms | Unified solution that combines technologies across multiple areas of the software development lifecycle. | +| Developer Tools | Continuous Integration and Deployment | CI/CD tools and services that support building and deploying code for software and systems. | +| Developer Tools | Development Environments | Tools and services that support authoring code for software and systems. | +| Developer Tools | Source Code Management | Tools and services that support version control of code for software and systems. | +| Developer Tools | Quality Assurance | Tools and services that support testing code for software and systems. | +| Developer Tools | Other (Developer Tools) | Developer Tools services that do not fall into one of the defined subcategories. | +| Identity | Identity and Access Management | Technologies that ensure users have appropriate access to resources. | +| Identity | Other (Identity) | Identity services that do not fall into one of the defined subcategories. | +| Integration | API Management | Creation, publishing, and management of application programming interfaces. | +| Integration | Messaging | Asynchronous communication between distributed applications. | +| Integration | Workflow Orchestration | Design, execution, and management of business processes and workflows. | +| Integration | Other (Integration) | Integration services that do not fall into one of the defined subcategories. | +| Internet of Things | IoT Analytics | Examination of data collected from IoT devices. | +| Internet of Things | IoT Platforms | Unified solution that combines IoT data collection, processing, visualization, and device management. | +| Internet of Things | Other (Internet of Things) | Internet of Things (IoT) services that do not fall into one of the defined subcategories. | +| Management and Governance | Architecture | Planning, design, and construction of software systems. | +| Management and Governance | Compliance | Adherance to regulatory standards and industry best practices. | +| Management and Governance | Cost Management | Monitoring and controlling expenses of systems and services. | +| Management and Governance | Data Governance | Management of the availability, usability, integrity, and security of data. | +| Management and Governance | Disaster Recovery | Plans and procedures that ensure systems and services can recover from disruptions. | +| Management and Governance | Endpoint Management | Tools that configure and secure access to devices. | +| Management and Governance | Observability | Monitoring, logging, and tracing of data to track the performance and health of systems. | +| Management and Governance | Support | Assistance and expertise supplied by providers. | +| Management and Governance | Other (Management and Governance) | Management and governance services that do not fall into one of the defined subcategories. | +| Media | Content Creation | Production of media content. | +| Media | Gaming | Development and delivery of gaming services. | +| Media | Media Streaming | Multimedia delivered and rendered in real-time on devices. | +| Media | Mixed Reality | Technologies that blend real-world and computer-generated environments. | +| Media | Other (Media) | Media services that do not fall into one of the defined subcategories. | +| Migration | Data Migration | Movement of stored data from one location to another. | +| Migration | Resource Migration | Movement of resources from one location to another. | +| Migration | Other (Migration) | Migration services that do not fall into one of the defined subcategories. | +| Mobile | Other (Mobile) | All Mobile services. | +| Multicloud | Multicloud Integration | Environments that facilitate consumption of services from multiple cloud providers. | +| Multicloud | Other (Multicloud) | Multicloud services that do not fall into one of the defined subcategories. | +| Networking | Application Networking | Distribution of incoming network traffic across application-based workloads. | +| Networking | Content Delivery | Distribution of digital content using a network of servers (CDNs). | +| Networking | Network Connectivity | Facilitates communication between networks or network segments. | +| Networking | Network Infrastructure | Configuration, monitoring, and troubleshooting of network devices. | +| Networking | Network Routing | Services that select paths for traffic within or across networks. | +| Networking | Network Security | Protection from unauthorized network access and cyber threats using firewalls and anti-malware tools. | +| Networking | Other (Networking) | Networking services that do not fall into one of the defined subcategories. | +| Security | Secret Management | Information used to authenticate users and systems, including secrets, certificates, tokens, and other keys. | +| Security | Security Posture Management | Tools that help organizations configure, monitor, and improve system security. | +| Security | Threat Detection and Response | Collect and analyze security data to identify and respond to potential security threats and vulnerabilities. | +| Security | Other (Security) | Security services that do not fall into one of the defined subcategories. | +| Storage | Backup Storage | Secondary storage to protect against data loss. | +| Storage | Block Storage | High performance, low latency storage that provides random access. | +| Storage | File Storage | Scalable, sharable storage for file-based data. | +| Storage | Object Storage | Highly available, durable storage for unstructured data. | +| Storage | Storage Platforms | Unified solution that supports multiple storage types. | +| Storage | Other (Storage) | Storage services that do not fall into one of the defined subcategories. | +| Web | Application Platforms | Integrated environments that run web applications. | +| Web | Other (Web) | Web services that do not fall into one of the defined subcategories. | +| Other | Other (Other) | Services that do not fall into one of the defined categories. | + +## Introduced (version) + +1.1 diff --git a/supporting_content/columns/servicesubcategory.md b/supporting_content/columns/servicesubcategory.md new file mode 100644 index 000000000..5834fef2a --- /dev/null +++ b/supporting_content/columns/servicesubcategory.md @@ -0,0 +1,210 @@ +# Column: ServiceSubcategory + +## Example provider mappings + +Current column mappings found in available data sets: + +| Provider | Data set | Column | +| --------- | ------------------------ | ------------------------------------------ | +| AWS | FOCUS; CUR | None | +| GCP | FOCUS; Big Query Billing Export | None | +| Microsoft | FOCUS; Cost details | None | +| OCI | FOCUS; Cost reports | None | + +The creation of this publicly-available column shall be net-new for the cloud service providers, though they may already maintain their own proprietary Subcategories. For example, AWS describes their Database Subcategories [here](https://docs.aws.amazon.com/whitepapers/latest/aws-overview/database.html). + +## Discussion / Scratch space + +### Principles + +In addition to the principles as defined during the creation of Service Categories in FOCUS 0.5, the following principles shall also be followed when constructing Service Subcategories: + +- Undercategorize rather than overcategorize where there is not broad consensus and/or materiality. + - Allow the community to advocate for new Subcategories (and Categories) in future releases, and leave Services uncategorized and/or unsubcategorized in the meantime. +- Assign each Service to the one (and only one) Subcategory that describes its primary function. + - The Service hierarchy is meant to serve as a relatively high-level set of groupings that primarily address the needs of the Executive persona. A given Service can fulfill multiple functions across and within organizations, and so the assignment of a Service to one and only one Category and Subcategory may be inaccurate from org to the next. However, this hierarchy will then give the Practitioner a solid place to start, and they can make a few tweaks to its composition to meet their org's needs rather than create a hierarchy from scratch. Ultimately, the creation and maintenance of the Service hierarchy requires us to embrace the imperfect and somewhat subjective nature of assigining a given Service to a single Category / Subcategory. + - The (forthcoming) SKU hierarchy will be an opportunity to get very specific on the categorizations of cost and usage activity. For example, GCP maintains a seven-level taxonomy for every SKU, and this will hopefully more concretely address the lower-level reporting needs of the Engineering persona. + - Use the "Platforms" suffix whenever a subcategory is needed to cover products and services that span multiple other subcategories. + - Avoid a "Platforms" subcategory if the service category does not have other subcategories. + +### Sample provider mappings +Here are sample subcategorizations of various services across the AWS, Azure, and GCP landscape. + +To be clear, this list is neither exhaustive nor prescriptive nor suggestive; it shall be up to the providers to decide where to assign their services, and FOCUS shall merely provide the list of available Subcategories. This list was generated merely for illustrative purposes when constructing the subcategories. + +| Service Category | Service Subcategory | AWS | Azure | GCP | +| ------------------------- | ------------------------------------- | ------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ | +| AI and Machine Learning | AI Platforms | | AI Services, Video Indexer, Autonomous Systems, Syntex, Intelligent Recommendations | | +| AI and Machine Learning | Bots | Lex, Robomaker | Bot Service, Health Bot | | +| AI and Machine Learning | Generative AI | Bedrock, Q | | Gemini, Vertex AI | +| AI and Machine Learning | Machine Learning | Sagemaker, Sagemaker Savings Plan, Lookout, Personalize | Machine Learning | | +| AI and Machine Learning | Natural Language Processing | Polly, Transcribe, Translate, Lex | | natural language AI, text-to-speech, Speech-to-text, Document AI | +| AI and Machine Learning | Other (AI and Machine Learning) | Capacity Blocks, Rekognition | | | +| Analytics | Analytics Platforms | Athena | Fabric, Synapse, Data Explorer, Modeling and Simulation Workbench, Data Manager for Energy, Health Data Services | | +| Analytics | Business Intelligence | QuickSight | Power BI, Analysis Services, Grafana | Looker | +| Analytics | Data Processing | EMR, Batch, Glue, Data Pipeline | Databricks, HDInsight, Data Lake Analytics, Analysis Services, Data Catalog, Genomics | Cloud Composer, Dataflow, Dataproc | +| Analytics | Search | Cognitive Search, CloudSearch, Elasticsearch, Kendra | Azure AI Search | Vertex AI Search | +| Analytics | Streaming Analytics | Kinesis | Stream Analytics | | +| Analytics | Other (Analytics) | Clean Rooms | | | +| Business Applications | Productivity and Collaboration | WorkDocs, WorkLink, WorkMail, Chime | Microsoft 365, Teams, Power Platform | Workspace | +| Business Applications | Other (Business Applications) | Supply Chain, Connect | Dynamics 365, Community Training | | +| Compute | Containers | EKS, ECS | AKS, Container Apps, Container Instances, Container Registry, Container Service, Service Fabric | GKE, Cloud Run | +| Compute | End User Computing | AppStream | Virtual Desktop, Lab Services, Citrix | | +| Compute | Quantum Compute | Braket | Quantum | | +| Compute | Serverless Compute | Lambda | Cloud Services, Batch | Cloud Functions, Cloud Run | +| Compute | Virtual Machines | EC2 | BareMetal Infrastructure, Dedicated Host, VMware Solution, SAP on Azure, Virtual Machine Scale Sets, Virtual Machines | Compute Engine | +| Compute | Other (Compute) | Compute Savings Plan | Savings Plan for Compute | Flex CUDs | +| Databases | Caching | ElastiCache, MemoryDB | Cache for Redis | Memorystore | +| Databases | Data Warehouses | Redshift | (none) | BigQuery | +| Databases | Ledger Databases | QLDB, Managed Blockchain | Confidential Ledger | Blockchain Node Engine | +| Databases | NoSQL Databases | DynamoDB, Neptune, Cassandra, SimpleDB, AppSync | Cosmos DB | Datastore, Bigtable, Firestore | +| Databases | Relational Databases | RDS, Aurora | MariaDB, MySQL, PostgreSQL, SQL Database | Cloud SQL, AlloyDB, Spanner | +| Databases | Time Series Databases | Timestream | (none) | | +| Databases | Other (Databases) | Cloud Directory | (none) | | +| Developer Tools | Developer Platforms | CodeCatalyst | DevOps, GitHub, App Center | | +| Developer Tools | Continuous Integration and Deployment | CodeDeploy, CodePipeline, CodeBuild, CodeArtifact | | Cloud Build, Cloud Deploy | +| Developer Tools | Development Environments | | Trusted Signing, Dev Box, Managed DevOps Pools | Cloud Code | +| Developer Tools | Source Code Management | CodeCommit | | | +| Developer Tools | Quality Assurance | CodeGuru | Playwright Testing, Load Testing, Test Base for M365 | | +| Developer Tools | Other (Developer Tools) | re:Post Private | | | +| Identity | Identity and Access Management | IAM | Entra ID, External Identities, Domain Services | Cloud Identity, IAM | +| Identity | Other (Identity) | | | | +| Integration | API Management | API Gateway | API Center, API Management, Microsoft Graph | | +| Integration | Messaging | SQS, SNS, EventBridge, Pinpoint | Service Bus, Relay, Event Grid, Communcation Services, Notification Hubs | Cloud Pub/Sub, Firebase | +| Integration | Workflow Orchestration | Managed Workflows, Entity Resolution | Apache Airflow, Data Factory, Logic Apps, Automation | | +| Integration | Other (Integration) | | | | +| Internet of Things | IoT Analytics | | Digital Twins, Time Series Insights, FarmBeats | | +| Internet of Things | IoT Platforms | IoT Core, Greengrass | IoT Central, IoT Hub, Windows for IoT, Defender for IoT | | +| Internet of Things | Other (Internet of Things) | | | | +| Management and Governance | Architecture | Well-Architected Tool, Config, Trusted Advisor | (none) | | +| Management and Governance | Compliance | Compliance | Policy | | +| Management and Governance | Cost Management | Cost Explorer, Billing Conductor | Reservations | Invoice | +| Management and Governance | Data Governance | DataZone | Purview | Dataplex | +| Management and Governance | Disaster Recovery | DRS (Disaster Recovery Service) | Chaos Studio, Site Recovery | | +| Management and Governance | Endpoint Management | | Intune, Universal Print, Defender for Endpoint | | +| Management and Governance | Observability | CloudWatch, CloudTrail, X-Ray, Grafana | Monitor | Cloud Monitoring, Cloud Logging, Cloud Trace | +| Management and Governance | Support | AWS Support | Support | Customer Care ([Support](https://cloud.google.com/support/?hl=en)) | +| Management and Governance | Other (Management and Governance) | | | | +| Media | Content Creation | Deadline | | | +| Media | Gaming | | PlayFab | | +| Media | Media Streaming | | Media Services | | +| Media | Mixed Reality | | Spatial Anchors, Object Anchors, Remote Rendering | | +| Media | Other (Media) | Deadline | | | +| Migration | Data Migration | Database Migration, Snowball, Import/Export | Database Migration Service, Data Box, Import/Export, Data Share, File Sync | | +| Migration | Resource Migration | App Migration | Migrate | | +| Migration | Other (Migration) | | | | +| Mobile | Other (Mobile) | | | | +| Multicloud | Multicloud Integration | | Arc, Stack Edge, Stack HCI | | +| Multicloud | Other (Multicloud) | Outposts | | Anthos, AlloyDB Omni | +| Networking | Application Networking | ELB, Application Load Balancer | Load Balancer, Application Gateway, Traffic Manager | | +| Networking | Content Delivery | CloudFront | Front Door, CDN | | +| Networking | Network Connectivity | Ground Station, VPN Gateway, PrivateLink, Network Connect | Peering, 5G Core, Orbital, VPN Gateway, NAT Gateway, PrivateLink, Virtual WAN | Cloud VPN, Cloud Interconnect | +| Networking | Network Infrastructure | VPC, VPC Flow Logs | Virtual Network, Network Watcher, Network Function Manager | Shared VPC (XPN) | +| Networking | Network Routing | Route 53 | ExpressRoute, DNS | | +| Networking | Network Security | Web Application Firewall | Firewall, DDoS Protection, Bastion | | +| Networking | Other (Networking) | | | Networking | +| Security | Secret Management | Secrets Manager, Certificate Manager, KMS, CloudHSM, Payment Cryptography | Key Vault, Dedicated HSM | Secret Manager, Certificate Authority, KMS | +| Security | Security Posture Management | Security Hub, Macie | Defender for Cloud, Copilot for Security | | +| Security | Threat Detection and Response | GuardDuty, Inspector, Detective, Shield, Security Lake | Dynamics 365 Fraud Protection | | +| Security | Other (Security) | | | | +| Storage | Backup Storage | Backup | Backup | | +| Storage | Block Storage | EBS | Managed disk, ElasticSAN | Persistent Disks, Local SSDs | +| Storage | File Storage | EFS | NetApp Files | Hyperdisk | +| Storage | Object Storage | S3, Glacier | ADLS | Cloud Storage | +| Storage | Storage Platforms | | Storage Accounts, HPC Cache, StoreSimple | | +| Storage | Other (Storage) | | | | +| Web | Application Platforms | Elastic Beanstalk | App Service, Spring Apps | App Engine | +| Web | Other (Web) | Lightsail | App Configuration, Maps, SignalR Service, Fluid Relay | Maps {Directions API, Distance Matrix API, Geolocation API, etc.} | +| Other | Other (Other) | | | + +### Discussion Outcomes + +A series of open questions were discussed over the course of July and August 2024, both in the [draft spreadsheet](https://docs.google.com/spreadsheets/d/1aYq79sWp8TK4zbcSKUb-gRIBei3fERVwAgDJ5ezZf1w/edit?usp=sharing) and in Task Force (TF) and Member calls. This section attempts to describe the largest topics and outcomes of those discussions. + +#### Shall the Category composition change from FOCUS 1.0? + +With Subcategories now in scope for FOCUS 1.1, there was then the potential of changing Categories. For example: + +- `Identity` could become a child Subcategory of `Security`. +- `Web` and `Mobile` could be grouped together into a net-new category (proposed `Front-end` or `Application Tools`). +- Activity that is truly cross-categorical could be placed in a net-new category (proposed `Crossfunctional`) separate from `Other`, which is more of an uncategorized placeholder. +- `Integration` could be rescoped and renamed `Data Management` to be more inclusive of Service Subcategories such as Data Processing and API Management. +- `Multicloud` could be rescoped and renamed `Hybrid and Multicloud` to be more inclusive of on-premises Services. + +After much discussion, particularly on the Aug 6 TF1 call, it became clear that the "burden of proof" for changing existing Categories is higher, given that some of the group feels this to constitute a "breaking change". Some of the group felt that the Service hierarchy should be considered more of a "living document" that is revisited from one FOCUS release to another, in order to stay more tightly aligned with the slowly-changing nature of Service categorizations; others felt that would be prohibitively disruptive for FOCUS consumers who have constructed various downstream artifacts and depend on a certain Category and Subcategory composition. + +_Outcome_: leave the Category composition in place for FOCUS 1.1 and narrow scope of this release to only add Subcategories underneath them, leaving the door open to alter the Category composition in a future release (either major or not, pending a larger decision around what constitutes a "breaking change"). + +#### Shall the Subcategory (and Category) assignment describe the activity's _use case_? + +Consider the example of [AWS Inf2 VM instances](https://aws.amazon.com/ec2/instance-types/inf2/). These instance types are purpose-built to be used for AI and ML use cases, and so any related cost and usage activity belongs in the Category of `AI and Machine Learning`, right? + +Not so fast. While the _intended purpose_ of this VM is for AI use cases, it's still a VM that technically could be used for anything. Ultimately, we cannot attempt to categorize the _SKU_ with our Service Subcategory; we can only categorize the Service, which in this case is still EC2, which therefore falls into `Compute > Virtual Machines`. When FOCUS implements a SKU taxonomy / hierarchy, we would be able to get more specific about the use of Inf2 vs, say, T2 instances. Any reporting that attempted to better convey the use case would either need to leverage that future hierarchy or an appropriate tag of the involved Resources that conveys purpose. + +This was discussed at the Jul 30 TF1 call, and the strong majority, if not consensus, opinion was that examples such as these should remain in their Service's assignment, regardless of use case. However, it does not dismiss the fair point that a Service Category of AI & Machine Learning will exclude Services that can be used for AI and ML purposes. That is an issue that goes beyond the scope of these columns and must be solved with other mechanisms. + +_Outcome_: Service Category and Subcategory shall describe the Service's primary function -- not the use case of the usage or SKU. + +#### Where do Commitment Discounts belong? + +Commitment Discounts have various models that could belong in various places of a Service category hierarchy. For example: + +- An Azure reservation for D8as v5 can be both Categorized (i.e. `Compute`) and Subcategorized (i.e. `Virtual Machines`). +- An AWS Compute savings plan can be Categorized (i.e. `Compute`) but not Subcategorized (e.g. it can be applied to both `Virtual Machines` and `Serverless Compute`). +- An OCI Credit can neither be Categorized nor Subcategorized (e.g. it can be applied to a wide variety of usage). + +Based on that, there was a robust discussion, particularly on the Jul 23 TF1 and Aug 8 Member calls, as to where Commitment Discounts belong. Do they deserve their own Subcategories (e.g. `Commitments (Compute)`, `Commitments (Databases)`) underneath each Category? Do they also deserve their own Category (e.g. `Commitments` or `Crossfunctional`)? + +_Outcome_: given the decision not to change the Category composition, and given the principle of undercategorizing rather than overcategorizing: + +- Commitment Discounts with a natural Category / Subcategory shall be placed therein. +- Commitment Discounts with a natural Category but no Subcategory shall be placed in `Other ()`. +- Commitment Discounts with no natural Category or Subcategory shall be placed in `Other (Other)`. + +#### Shall certain technologies be given their own Categories? + +The group discussed the possibility of "graduating" Services to their own net-new categories, such as `Blockchain`, `Containers`, and `Mixed Reality`. These are technologies for which some or all of the three major cloud service providers have created their own Categories, and there is certainly a use case for being able to easily build reports to show those (and only those) Services. + +Given the decision not to change the Category composition on the Aug 6 TF1 call, this became a moot discussion. However, the group did discuss some specific examples, particularly on the Jul 23 TF1 and Jul 25 Member calls: + +- `Blockchain` belongs under `Databases > Ledger`. +- `Containers` belongs under `Compute > Containers`. +- `Support` belongs under `Management and Governance`. +- `Mixed Reality` does not deserve its own Category. +- `Industry Specific` does not deserve its own Category. +- `Marketplace` Services shall be placed into the Category and Subcategory aligned with their purpose, rather than placed into a `Marketplace` Category. + +_Outcome_: No Category additions or changes at this time. + +#### What shall we call the "unsubcategorized" Subcategory? + +Each Category carries an "Other" Subcategory to allow the providers to provide a Category without a Subcategory. A vote was issued via Slack on Aug 13 with the following options: + +:one: `Uncategorized ()` +:two: `Other ()` +:three: `Uncategorized` +:four: `Other` + +The following considerations were included: + +- Brevity, simplicity, and consistency of Subcategory names (e.g. “Uncategorized (Management and Governance)” is pretty long). +- Delineation of Category values from Subcategory values (e.g. use of Subcategory “Other” underneath all Categories “Compute”, “Databases” and “Other” could be confusing). +- Analytical utility of Subcategory without Category context (e.g. uncategorized Compute from uncategorized Databases are automatically separated in a bar chart). + +_Outcome_: Option :two: was chosen. + +#### Why do some of the Categories lack Subcategories beyond "Other"? + +Per the principles and some of the outcomes described above, we have leaned towards subcategorizing only those Categories on which we had broad consensus and/or could target significant usage. Several of the existing Categories do not have sufficient Service counts and/or activity to allow designating Subcategories at a high degree of confidence, and future FOCUS versions can add such groupings if and when requested by the community. + +#### Shall this column be mandatory or optional? + +There was some discussion around this at the 8/15 Member call. Some felt that Service Subcategory should be mandatory because Service Category is mandatory, and together they form a hierarchy. Others felt that provider adoption would be easier if the column were not required. Still others felt that making the column mandatory, even populated completely with Other, would entice FOCUS consumers to petition their provider(s) to populate the column with actual Subcategories. + +Ultimately, it seemed that the majority leaned towards making it optional. + +_Outcome_: Optional. + + + + From 52abaeb57840cfaf3fa04b3260a850e56eeeb145 Mon Sep 17 00:00:00 2001 From: AWS-ZachErdman <157180770+AWS-ZachErdman@users.noreply.github.com> Date: Thu, 19 Sep 2024 20:59:44 -0700 Subject: [PATCH 31/52] Dedicated SKU column (for issue #495) (#516) **Lead Maintainer**: Zach ### Documents: * Folder #495 : [SKU Properties & Providers Alignment](https://drive.google.com/drive/u/0/folders/11CDin-7o7KNGrdCzgq7gdVwQFcJ2l8aq) by Zach moved to folder #495 * Document: [SKU Details from Providers (FOCUS)](https://docs.google.com/document/d/1PdF8VQ5Ad4kDmrTlSEzWGOitwyEeQHR5B13hPWArMg0/edit#heading=h.ezdq0hltg6) * Spreadsheet: [24.08.08 - Alternative-Column-Names-for-UsageType](https://docs.google.com/spreadsheets/d/1-n_-z1bWKKwEbSXfiICHl0ff-uC9qAdDaDYhQGsagEM/edit?usp=sharing) * PR [#516](https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/pull/516) Initial Draft of UsageType * Approval date: Sep 05 --------- Co-authored-by: Christopher Harris Co-authored-by: Joaquin Co-authored-by: Karl <133434112+kk09v@users.noreply.github.com> Co-authored-by: Udam Dewaraja --- specification/columns/columns.mdpp | 1 + specification/columns/skumeter.md | 43 +++++++++++++++++++++++++ supporting_content/columns/skumeter.md | 44 ++++++++++++++++++++++++++ 3 files changed, 88 insertions(+) create mode 100644 specification/columns/skumeter.md create mode 100644 supporting_content/columns/skumeter.md diff --git a/specification/columns/columns.mdpp b/specification/columns/columns.mdpp index aac55c69a..c1dc78124 100644 --- a/specification/columns/columns.mdpp +++ b/specification/columns/columns.mdpp @@ -46,6 +46,7 @@ The FOCUS specification defines a group of columns that provide qualitative valu !INCLUDE "servicename.md",1 !INCLUDE "servicesubcategory.md",1 !INCLUDE "skuid.md",1 +!INCLUDE "skumeter.md",1 !INCLUDE "skupricedetails.md",1 !INCLUDE "skupriceid.md",1 !INCLUDE "subaccountid.md",1 diff --git a/specification/columns/skumeter.md b/specification/columns/skumeter.md new file mode 100644 index 000000000..6b642abe2 --- /dev/null +++ b/specification/columns/skumeter.md @@ -0,0 +1,43 @@ +# SKU Meter + +The SKU Meter describes the functionality being metered or measured by a particular SKU in a charge. + +Providers often have billing models in which multiple SKUs exist for a given service to describe and bill for different functionalities for that service. For example, an object storage service may have separate SKUs for functionalities such as object storage, API requests, data transfer, encryption, and object management. This field helps practitioners understand which functionalities are being metered by the different SKUs that appear in a FOCUS dataset. + +The SkuMeter column adheres to the following requirements: + +* SkuMeter MUST be present in the billing data when when the provider includes a [SkuId](#skuid). +* SkuMeter MUST be of type String. +* SkuMeter MUST be null when SkuId is null. +* SkuMeter SHOULD NOT be null when SkuId is not null. +* SkuMeter SHOULD remain consistent over time for a given SkuId. + +## Examples + +Compute Usage, Block Volume Usage, Data Transfer, API Requests + +## Column ID + +SkuMeter + +## Display Name + +SKU Meter + +## Description + +Describes the functionality being metered or measured by a particular SKU in a charge. + +## Content Constraints + +| Constraint | Value | +|:----------------|:-----------------| +| Column type | Dimension | +| Feature level | Conditional | +| Allows nulls | True | +| Data type | String | +| Value format | \ | + +## Introduced (version) + +1.1 diff --git a/supporting_content/columns/skumeter.md b/supporting_content/columns/skumeter.md new file mode 100644 index 000000000..4806f91d9 --- /dev/null +++ b/supporting_content/columns/skumeter.md @@ -0,0 +1,44 @@ +# Column: SkuMeter + +## Example provider mappings + +Current column mappings found in available data sets: + +| Provider | Data set | Column | +|-----------|--------------------------|------------------------------------| +| AWS | CUR | line_item_usage_type | +| GCP | Big Query Billing Export | service.description | +| Microsoft | Cost details | MeterName | +| OCI | Cost reports | TBD | + +## Background + +Cloud Services, such as managed databases, virtual machines for compute, and object storage, have billing models in which the usage of that service is metered and then charged based on multiple parameters. For example, Amazon S3 charges customers for Storage, API requests, Data transfer, Encryption, Object management, Replication, and custom API requests, and ALL of these functionalities are metered and billed under the service name “Amazon S3”. + +Cloud providers use different SKUs to differentiate between these different types of usage of a given service, but the SKU is a GUID that does not have any semantic meaning to a FinOps practitioner. This is problematic because as a FinOps practitioner, I want to be able to understand what the breakdown is of how I am being charged for a particular service so that I can use this information to report what the primary cost drivers are for a particular service and so that I can make optimization decisions. For example, I might want to understand what my data transfer costs within all of my Amazon S3 charges so that I can recommend my development team to change their storage access patterns in order to achieve cost savings. + +Research across cloud providers suggests that there are 4 main categories of attributes that contribute to a SKU. They are: +Product: What is the public name of the thing (eg the resource or service) being sold? +Region: Where is the thing being sold? +Function: What is the functionality being measured and sold? +Size: How big is the thing (eg the resource or service) being sold (if applicable)? + +This column addresses the "Function" attribute of a SKU by making it a first class part of the FOCUS schema. + +## Problem + +Today, FOCUS does not have any columns that enable FinOps practitioners to understand the meaning of different SKUs that appear and group them (such as with SQL GROUP BY) in order to better understand the main contributors to the cost of a given service. + +As a practitioner, I want to be able to write a SQL query that easily breaks down my charges for a given service so that I can understand how each kind of "Function" is contributing to the overall cost of a service. + +## Solution Discussion + +**Short term (V1.1):** +Given that these data may not be readily available immediately from providers, we are starting with a single column which providers can populate with as much useful data as they can that helps meet this need. + +We believe it will be OK for providers to decide how to populate this column with the data they have available today. This means the data within this column may cover more than just the "Function" attribute described above. When populating this column, Providers should keep in mind that it will be painful for practitioners if the provider decides to change it in the future. + +**Longer term (timeframe TBD):** +In the future we would like to move to separate columns, one for each of Product, Region, Function, Size, and have each of these columns be populated with only this data. + +There may be an opportunity for some of these values to be normalized, or at least the format standardized, but some values will need to be provider-specific. This is similar to how the Unit Attribute works today where the most common units are normalized across providers (such as Hours), while other units are provider specific. \ No newline at end of file From 1b39b0c8a5b28fea07c334caf5b07d09ba2b50ba Mon Sep 17 00:00:00 2001 From: Christopher Harris Date: Fri, 20 Sep 2024 13:28:00 -0400 Subject: [PATCH 32/52] Commitment Discount Appendix (#528) An appendix detailing how various commitment discount purchases and usage records are modeled through various examples. --------- Co-authored-by: Shawn Alpay <77511110+salpaysenturus@users.noreply.github.com> Co-authored-by: Irena Jurica Co-authored-by: Joaquin Co-authored-by: AWS-ZachErdman <157180770+AWS-ZachErdman@users.noreply.github.com> Co-authored-by: Karl <133434112+kk09v@users.noreply.github.com> Co-authored-by: Udam Dewaraja --- specification/appendix/appendix.mdpp | 1 + .../appendix/commitment_discounts.md | 278 ++++++++++++++++++ specification/glossary.md | 2 +- specification/markdownlnt.cfg | 1 + 4 files changed, 281 insertions(+), 1 deletion(-) create mode 100644 specification/appendix/commitment_discounts.md diff --git a/specification/appendix/appendix.mdpp b/specification/appendix/appendix.mdpp index 3f9ea0cbd..4101a5243 100644 --- a/specification/appendix/appendix.mdpp +++ b/specification/appendix/appendix.mdpp @@ -2,6 +2,7 @@ *This section is non-normative.* +!INCLUDE "commitment_discounts.md",1 !INCLUDE "grouping_constructs_for_resources_and_or_services.md",1 !INCLUDE "origination_of_cost_data.md",1 !INCLUDE "examples/examples.mdpp",1 diff --git a/specification/appendix/commitment_discounts.md b/specification/appendix/commitment_discounts.md new file mode 100644 index 000000000..ef845b6de --- /dev/null +++ b/specification/appendix/commitment_discounts.md @@ -0,0 +1,278 @@ +# Commitment Discounts + +A [*commitment discount*](glossary:commitment-discount) is a billing discount model that offers reduced rates on preselected [SKUs](#glossary:sku) in exchange for an obligated usage or spend amount over a predefined [*term*](glossary:term). *Commitment discounts* typically consist of purchase and usage records within cost and usage datasets. + +Usage-based *commitment discounts* obligate a customer to a predetermined amount of usage over a preselected *term*. In some cases, usage-based *commitment discounts* also feature [*commitment flexibility*](glossary:commitment-flexibility) which may expand the types of *resources* that a *commitment discount* can cover. It is important to note when mixing *commitment discounts* with and without *commitment flexibility*, the `CommitmentDiscountUnit` should reflect this difference. + +Spend-based commitment discounts obligate a customer to a predetermined amount of spend over a preselected *term*. In the usage examples below, each [*row*](glossary:row) measures the monetary amount of the hourly commit consumed by the *commitment discount*, so the `CommitmentDiscountUnit` chosen is "USD", or the [*billing currency*](glossary:billing-currency). + +## Purchasing + +While customers are bound to the *term* of a *commitment discounts*, providers offer some or all of the following payment options before and/or during the *term*: + +* *All Upfront* - The *commitment discounts* is paid in full before the *term* begins. +* *No Upfront* - The *commitment discounts* is paid on a repeated basis, typically over each [*billing period*](glossary:billing-period) of the *term*. +* *Partial Upfront* - Some of the *commitment discounts* is paid before the *term* begins, and the rest is paid repeatedly over the *term*. + +For example, if a customer buys a 1-year, spend-based *commitment discount* with a $1.00 hourly commit and pays with the partial option, the *commitment discount's* payment consists of a one-time purchase in the beginning of the *term* *and* monthly recurring purchases with the following totals: + +1. *One-Time* - $4,380 (`24 hours * 365 days * $1.00 * 0.5`) +2. *Recurring* - $182.50 (`24 hours * 365 days * $1.00 / 12 months`) + +## Usage + +Commitment discounts follow a "use-it-or-lose-it" model where the [*amortization*](glossary:amortization) of a *commitment discount's* purchase applies evenly to eligible *resources* over each [*charge period*](glossary:charge-period) of the *term*. + +For example, if a customer buys a spend-based *commitment discount* with a $1.00 hourly commit in January (31 days), only $1.00 is eligible for consumption for each hourly *charge period*. If a customer has eligible *resources* running during this *charge period*, an amount of up to $1.00 will be allocated to these *resources*. Conversely, if a customer does have eligible *resources* running that fully take advantage of this $1.00 during this *charge period*, then some or all of this amount will go to waste. + +## Commitment Discounts in FOCUS + +Within the FOCUS specification, the following examples demonstrate how a *commitment discount* appears across various payment and usage scenarios. + +### Purchase *Rows* + +All *commitment discount* purchases appear with a positive `BilledCost`, `PricingCategory` as "Committed", and with the *commitment discount's* id populating both the `ResourceId` and `CommitmentDiscountId` value. One-time purchases appear as a single record with `ChargeCategory` as "Purchase", `ChargeFrequency` as "One-Time", and the total quantity and units for *commitment discount's* *term* reflected as `CommitmentDiscountQuantity` and `CommitmentDiscountUnit`, respectively. + +Recurring purchases are allocated across all corresponding *charge periods* of the *term* when `ChargeCategory` is "Purchase", `ChargeFrequency` is "Recurring", and `CommitmentDiscountQuantity` and `CommitmentDiscountUnit` are reflected only for that *charge period*. + +Using the same *commitment discount* example as above with a one-year, spend-based *commitment discount* with a $1.00 hourly commit purchased on Jan 1, 2023, various purchase options are available: + +#### Scenario #1: All Upfront + +The entire *commitment discount* is billed _once_ during the first *charge period* of the *term* for $8,670 (derived as `24 hours * 365 days * $1.00`). + +```json +[ + { + "BillingPeriodStartDate": "2023-01-01T00:00:00Z", + "BillingPeriodEndDate": "2023-02-01T00:00:00Z", + "ChargePeriodStartDate": "2023-01-01T00:00:00Z", + "ChargePeriodEndDate": "2024-01-01T00:00:00Z", + "ChargeCategory": "Purchase", + "ChargeFrequency": "One-Time", + "PricingCategory": "Committed", + "ResourceId": "", + "BilledCost": 8760.00, + "EffectiveCost": 0.00, + "CommitmentDiscountId": "", + "CommitmentDiscountQuantity": 8760.00, + "CommitmentDiscountUnit": "USD" + } +] +``` + +#### Scenario #2: No Upfront + +The *commitment discount* is billed across all 8,760 (`24 hours * 365 days`) *charge periods* of the *term* with $1.00 allocated to each *charge period* over the *term*. + +```json +[ + { + "BillingPeriodStartDate": "2023-01-01T00:00:00Z", + "BillingPeriodEndDate": "2023-02-01T00:00:00Z", + "ChargePeriodStartDate": "2023-01-01T00:00:00Z", + "ChargePeriodEndDate": "2023-01-01T01:00:00Z", + "ChargeCategory": "Purchase", + "ChargeFrequency": "Recurring", + "PricingCategory": "Committed", + "ResourceId": "", + "BilledCost": 1.00, + "EffectiveCost": 0.00, + "CommitmentDiscountId": "", + "CommitmentDiscountQuantity": 1.00, + "CommitmentDiscountUnit": "USD" + }, + + /* ... 8,759 more recurring purchase records for the *term* ... */ +] +``` + +#### Scenario #3: Partial Upfront + +With a 50/50 split, half of the commitment is billed _once_ during the first *charge period* of the *term* for $4,380 (derived as `24 hours * 182.5 days * $1.00`), and the other half is billed across each *charge period* over the term, derived as (`$1.00 * 8,760 hours * 0.5`). Amortized costs incur half of the amount (i.e. $0.50) from the one-time purchase and the other half from the recurring purchase. + +```json +[ + { + "BillingPeriodStartDate": "2023-01-01T00:00:00Z", + "BillingPeriodEndDate": "2023-02-01T00:00:00Z", + "ChargePeriodStartDate": "2023-01-01T00:00:00Z", + "ChargePeriodEndDate": "2024-01-01T00:00:00Z", + "ChargeCategory": "Purchase", + "ChargeFrequency": "One-Time", + "PricingCategory": "Committed", + "ResourceId": "", + "BilledCost": 4380.00, + "EffectiveCost": 0.00, + "CommitmentDiscountId": "", + "CommitmentDiscountQuantity": 4380.00, + "CommitmentDiscountUnit": "USD" + }, + { + "BillingPeriodStartDate": "2023-01-01T00:00:00Z", + "BillingPeriodEndDate": "2023-02-01T00:00:00Z", + "ChargePeriodStartDate": "2023-01-01T00:00:00Z", + "ChargePeriodEndDate": "2023-01-01T01:00:00Z", + "ChargeCategory": "Purchase", + "ChargeFrequency": "Recurring", + "PricingCategory": "Committed", + "ResourceId": "", + "BilledCost": 0.50, + "EffectiveCost": 0.00, + "CommitmentDiscountId": "", + "CommitmentDiscountQuantity": 0.50, + "CommitmentDiscountUnit": "USD" + }, + + /* ... 8,759 more recurring purchase records for the *term* ... */ +] +``` + +### Usage *Rows* + +*Amortization* of *commitment discounts* occur similarly regardless of how *commitment discount* purchases are made. The same usage-based or spend-based amount is applied evenly across all *charge periods* and potentially allocated to eligible *resources*. Continuing with the same *commitment discount* example, a one-year, spend-based *commitment discount* with a $1.00 hourly commit and 1 *resource* (for simplicity) yields 4 types of scenarios that can occur during a *charge period*: + +* Scenario #1: An eligible *resource* fully consumes the allocated amount (100% utilization) +* Scenario #2: No eligible *resource* consumes the allocated amount (0% utilization) +* Scenario #3: An eligible *resource* partially consumes the allocated amount (75% utilization) +* Scenario #4: An eligible *resource* fully consumes the $1.00 hourly commit with an overage (100% utilization + overage) + +#### Scenario #1: An eligible *resource* fully consumes the allocated amount (100% utilization) + +In this scenario, one eligible *resource* runs for the full hour and consumes $1.00, so one *row* allocated to the *resource* is produced. + +```json +[ + { + "BillingPeriodStartDate": "2023-01-01T00:00:00Z", + "BillingPeriodEndDate": "2023-02-01T00:00:00Z", + "ChargePeriodStartDate": "2023-01-01T00:00:00Z", + "ChargePeriodEndDate": "2023-01-01T01:00:00Z", + "ChargeCategory": "Usage", + "ChargeFrequency": "Usage-Based", + "PricingCategory": "Committed", + "ResourceId": "", + "ConsumedQuantity": 1, + "ConsumedUnit": "Hour", + "BilledCost": 0.00, + "EffectiveCost": 1.00, + "CommitmentDiscountId": "", + "CommitmentDiscountQuantity": 1.00, + "CommitmentDiscountStatus": "Used", + "CommitmentDiscountUnit": "USD" + } +] +``` + +#### Scenario #2: No eligible *resource* consumes the allocated amount (0% utilization) + +In this situation, the full eligible, $1.00 amount remained unutilized and results in 1 unused *row*. In this scenario, it is important to note that while `CommitmentDiscountQuantity` is not because $1 was still drawn down by the *commitment discount* even though, no *resource* was allocated, so `ConsumedQuantity` and `ConsumedUnit` are null. + +```json +[ + { + "BillingPeriodStartDate": "2023-01-01T00:00:00Z", + "BillingPeriodEndDate": "2023-02-01T00:00:00Z", + "ChargePeriodStartDate": "2023-01-01T00:00:00Z", + "ChargePeriodEndDate": "2023-01-01T01:00:00Z", + "ChargeCategory": "Usage", + "ChargeFrequency": "Usage-Based", + "PricingCategory": "Committed", + "ResourceId": "", + "ConsumedQuantity": null, + "ConsumedUnit": null, + "BilledCost": 0.00, + "EffectiveCost": 1.00, + "CommitmentDiscountId": "", + "CommitmentDiscountQuantity": 1.00, + "CommitmentDiscountStatus": "Unused", + "CommitmentDiscountUnit": "USD" + } +] +``` + +#### Scenario #3: An eligible *resource* partially consumes the allocated amount (75% utilization) + +In this scenario, one eligible *resource* runs for the full hour and consumes $0.75 of the $1.00 allocation. One *row* shows $0.75 to a *resource*, and the other *row* shows that $0.25 was unused. + +```json +[ + { + "BillingPeriodStartDate": "2023-01-01T00:00:00Z", + "BillingPeriodEndDate": "2023-02-01T00:00:00Z", + "ChargePeriodStartDate": "2023-01-01T00:00:00Z", + "ChargePeriodEndDate": "2023-01-01T01:00:00Z", + "ChargeCategory": "Usage", + "ChargeFrequency": "Usage-Based", + "PricingCategory": "Committed", + "ResourceId": "", + "ConsumedQuantity": 1, + "ConsumedUnit": "Hour", + "BilledCost": 0.00, + "EffectiveCost": 0.75, + "CommitmentDiscountId": "", + "CommitmentDiscountQuantity": 0.75, + "CommitmentDiscountStatus": "Used", + "CommitmentDiscountUnit": "USD" + }, + { + "BillingPeriodStartDate": "2023-01-01T00:00:00Z", + "BillingPeriodEndDate": "2023-02-01T00:00:00Z", + "ChargePeriodStartDate": "2023-01-01T00:00:00Z", + "ChargePeriodEndDate": "2023-01-01T01:00:00Z", + "ChargeCategory": "Usage", + "ChargeFrequency": "Usage-Based", + "PricingCategory": "Committed", + "ResourceId": "", + "ConsumedQuantity": null, + "ConsumedUnit": null, + "BilledCost": 0.00, + "EffectiveCost": 0.25, + "CommitmentDiscountId": "", + "CommitmentDiscountQuantity": 0.25, + "CommitmentDiscountStatus": "Unused", + "CommitmentDiscountUnit": "USD" + } +] +``` + +#### Scenario #4: An eligible *resource* fully consumes the $1.00 hourly commit with an overage (100% utilization + overage) + +In this scenario, one eligible *resource* runs for the full hour and is charged $1.50. One *row* shows that $1.00 was *amortized* from the *commitment discount*, and the other shows that $0.50 was charged as standard, on-demand spend. + +```json +[ + { + "BillingPeriodStartDate": "2023-01-01T00:00:00Z", + "BillingPeriodEndDate": "2023-02-01T00:00:00Z", + "ChargePeriodStartDate": "2023-01-01T00:00:00Z", + "ChargePeriodEndDate": "2023-01-01T01:00:00Z", + "ChargeCategory": "Usage", + "ChargeFrequency": "Usage-Based", + "PricingCategory": "Committed", + "ResourceId": "", + "ConsumedQuantity": 1, + "ConsumedUnit": "Hour", + "BilledCost": 0.00, + "EffectiveCost": 1.00, + "CommitmentDiscountId": "", + "CommitmentDiscountQuantity": 1.00, + "CommitmentDiscountStatus": "Used", + "CommitmentDiscountUnit": "USD" + }, + { + "BillingPeriodStartDate": "2023-01-01T00:00:00Z", + "BillingPeriodEndDate": "2023-02-01T00:00:00Z", + "ChargePeriodStartDate": "2023-01-01T00:00:00Z", + "ChargePeriodEndDate": "2023-01-01T01:00:00Z", + "ChargeCategory": "Usage", + "ChargeFrequency": "Usage-Based", + "PricingCategory": "Standard", + "ResourceId": "", + "ConsumedQuantity": 1, + "ConsumedUnit": "Hour", + "BilledCost": 0.50, + "EffectiveCost": 0.00 + } +] +``` diff --git a/specification/glossary.md b/specification/glossary.md index f3b4b56ce..70f761ea9 100644 --- a/specification/glossary.md +++ b/specification/glossary.md @@ -54,7 +54,7 @@ A billing discount model that offers reduced rates on preselected SKUs in exchan Commitment Flexibility -A feature of [*commitment discounts*](#glossary:commitment-discount) that may further transform the predetermind amount of usage purchased or consumed based on additional, provider-specific requirements. +A feature of [*commitment discounts*](#glossary:commitment-discount) that may further transform the predetermined amount of usage purchased or consumed based on additional, provider-specific requirements. Cloud Service Provider (CSP) diff --git a/specification/markdownlnt.cfg b/specification/markdownlnt.cfg index 1a2f234b2..6b2fae3d7 100644 --- a/specification/markdownlnt.cfg +++ b/specification/markdownlnt.cfg @@ -2,6 +2,7 @@ "plugins" : { "MD033" : { "enabled" : false }, "MD013" : { "enabled" : false }, + "MD031" : { "enabled" : false }, "MD041" : { "enabled" : false }, "additional_paths": "../custom_linter_rules/rule_md_990.py" } From 00dcc55886298efdcee617977a7fbcb37d46d62b Mon Sep 17 00:00:00 2001 From: Christopher Harris Date: Fri, 27 Sep 2024 00:49:19 -0400 Subject: [PATCH 33/52] [EDITORIAL] Fix single-word glossary term italics (#544) Change `[SKU](glossary:sku)` to `[*SKU*](glossary:sku)` (italicized) --- specification/appendix/commitment_discounts.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/appendix/commitment_discounts.md b/specification/appendix/commitment_discounts.md index ef845b6de..4ef9b8796 100644 --- a/specification/appendix/commitment_discounts.md +++ b/specification/appendix/commitment_discounts.md @@ -1,6 +1,6 @@ # Commitment Discounts -A [*commitment discount*](glossary:commitment-discount) is a billing discount model that offers reduced rates on preselected [SKUs](#glossary:sku) in exchange for an obligated usage or spend amount over a predefined [*term*](glossary:term). *Commitment discounts* typically consist of purchase and usage records within cost and usage datasets. +A [*commitment discount*](glossary:commitment-discount) is a billing discount model that offers reduced rates on preselected [*SKUs*](#glossary:sku) in exchange for an obligated usage or spend amount over a predefined [*term*](glossary:term). *Commitment discounts* typically consist of purchase and usage records within cost and usage datasets. Usage-based *commitment discounts* obligate a customer to a predetermined amount of usage over a preselected *term*. In some cases, usage-based *commitment discounts* also feature [*commitment flexibility*](glossary:commitment-flexibility) which may expand the types of *resources* that a *commitment discount* can cover. It is important to note when mixing *commitment discounts* with and without *commitment flexibility*, the `CommitmentDiscountUnit` should reflect this difference. From ea591ed21c27163159f7eba91c11ba7be8b299ca Mon Sep 17 00:00:00 2001 From: Christopher Harris Date: Fri, 27 Sep 2024 00:51:52 -0400 Subject: [PATCH 34/52] [Editorial] Normalize all instances of commitment discount flexibility as "commitment discount flexibility" (#545) ### Documents: * PR [#545](https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/pull/545) Normalize all instances of commitment discount flexibility as "commitment discount flexibility" "Commitment Flexibility" -> "Commitment Discount Flexibility" --- specification/appendix/commitment_discounts.md | 2 +- specification/columns/commitmentdiscountquantity.md | 2 +- specification/columns/commitmentdiscountunit.md | 2 +- specification/columns/skupriceid.md | 2 +- specification/glossary.md | 2 +- supporting_content/columns/effectivecost.md | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/specification/appendix/commitment_discounts.md b/specification/appendix/commitment_discounts.md index 4ef9b8796..ce9b079dd 100644 --- a/specification/appendix/commitment_discounts.md +++ b/specification/appendix/commitment_discounts.md @@ -2,7 +2,7 @@ A [*commitment discount*](glossary:commitment-discount) is a billing discount model that offers reduced rates on preselected [*SKUs*](#glossary:sku) in exchange for an obligated usage or spend amount over a predefined [*term*](glossary:term). *Commitment discounts* typically consist of purchase and usage records within cost and usage datasets. -Usage-based *commitment discounts* obligate a customer to a predetermined amount of usage over a preselected *term*. In some cases, usage-based *commitment discounts* also feature [*commitment flexibility*](glossary:commitment-flexibility) which may expand the types of *resources* that a *commitment discount* can cover. It is important to note when mixing *commitment discounts* with and without *commitment flexibility*, the `CommitmentDiscountUnit` should reflect this difference. +Usage-based *commitment discounts* obligate a customer to a predetermined amount of usage over a preselected *term*. In some cases, usage-based *commitment discounts* also feature [*commitment discount flexibility*](glossary:commitment-discount-flexibility) which may expand the types of *resources* that a *commitment discount* can cover. It is important to note when mixing *commitment discounts* with and without *commitment discount flexibility*, the `CommitmentDiscountUnit` should reflect this difference. Spend-based commitment discounts obligate a customer to a predetermined amount of spend over a preselected *term*. In the usage examples below, each [*row*](glossary:row) measures the monetary amount of the hourly commit consumed by the *commitment discount*, so the `CommitmentDiscountUnit` chosen is "USD", or the [*billing currency*](glossary:billing-currency). diff --git a/specification/columns/commitmentdiscountquantity.md b/specification/columns/commitmentdiscountquantity.md index 45f4922c8..79b096479 100644 --- a/specification/columns/commitmentdiscountquantity.md +++ b/specification/columns/commitmentdiscountquantity.md @@ -2,7 +2,7 @@ Commitment Discount Quantity is the amount of a [*commitment discount*](#commitment-discount) purchased or accounted for in *commitment discount* related [*rows*](#glossary:row) that is denominated in [*Commitment Discount Units*](#glossary:commitmentdiscountunit). The aggregated Commitment Discount Quantity across purchase records, pertaining to a particular [Commitment Discount ID](#commitmentdiscountid) during its [*term*](#glossary:term), represents the total *Commitment Discount Units* acquired with that commitment discount. For committed usage, the Commitment Discount Quantity is either the number of *Commitment Discount Units* consumed by a [*row*](glossary:#row) that is covered by a *commitment discount* or is the unused portion of a *commitment discount* over a *charge period*. Commitment Discount Quantity is commonly used in *commitment discount* analysis and optimization use cases and only applies to *commitment discounts*, not [*negotiated discounts*](#glossary:negotiated-discount). -When *CommitmentDiscountCategory* is "Usage" (usage-based *commitment discounts*), the Commitment Discount Quantity reflects the predefined amount of usage purchased or consumed. If *commitment flexibility* is applicable, this value may be further transformed based on additional, provider-specific requirements. When *CommitmentDiscountCategory* is "Spend" (spend-based *commitment discounts*), the Commitment Discount Quantity reflects the predefined amount of spend purchased or consumed. +When *CommitmentDiscountCategory* is "Usage" (usage-based *commitment discounts*), the Commitment Discount Quantity reflects the predefined amount of usage purchased or consumed. If [*commitment discount flexibility*](glossary:commitment-discount-flexibility) is applicable, this value may be further transformed based on additional, provider-specific requirements. When *CommitmentDiscountCategory* is "Spend" (spend-based *commitment discounts*), the Commitment Discount Quantity reflects the predefined amount of spend purchased or consumed. **Important:** When aggregating Commitment Discount Quantity for utilization calculations, it's important to exclude *commitment discount* purchases (i.e. when *ChargeCategory* is "Purchase") that are paid to cover future eligible charges (e.g., *Commitment Discount*). This exclusion helps prevent double counting of these quantities in the aggregation. diff --git a/specification/columns/commitmentdiscountunit.md b/specification/columns/commitmentdiscountunit.md index d4c9efb9d..39c8784db 100644 --- a/specification/columns/commitmentdiscountunit.md +++ b/specification/columns/commitmentdiscountunit.md @@ -13,7 +13,7 @@ The CommitmentDiscountUnit column adheres to the following requirements: In cases where the CommitmentDiscountUnit is not null, the following applies: * The CommitmentDiscountUnit MUST represent the unit used to measure the *commitment discount*. -* When accounting for *commitment flexibility*, the CommitmentDiscountUnit value SHOULD reflect this consideration. +* When accounting for [*commitment discount flexibility*](glossary:commitment-discount-flexibility), the CommitmentDiscountUnit value SHOULD reflect this consideration. ## Column ID diff --git a/specification/columns/skupriceid.md b/specification/columns/skupriceid.md index 66206fef7..dfbc94b54 100644 --- a/specification/columns/skupriceid.md +++ b/specification/columns/skupriceid.md @@ -8,7 +8,7 @@ The *SkuPriceId* column adheres to the following requirements: * *SkuPriceId* MUST define a single unit price used for calculating the charge. * [*ListUnitPrice*](#listunitprice) MUST be associated with the *SkuPriceId* in the provider published price list. * *SkuPriceId* MUST NOT be null when [*ChargeClass*](#chargeclass) is not "Correction" and [*ChargeCategory*](#chargecategory) is "Usage" or "Purchase", MUST be null when *ChargeCategory* is "Tax", and MAY be null for all other combinations of *ChargeClass* and *ChargeCategory*. -* A given value of *SkuPriceId* MUST be associated with one and only one [*SkuId*](#skuid), except in cases of commitment discount flexibility. +* A given value of *SkuPriceId* MUST be associated with one and only one [*SkuId*](#skuid), except in cases of [*commitment discount flexibility*](glossary:commitment-discount-flexibility). * If a provider does not have a *SkuPriceId* and wants to include information in columns linked to *SkuPriceId* such as *ListUnitPrice* or [*SkuPriceDetails*](#skupricedetails), the *SkuId* MAY be used in the *SkuPriceId* column as long as it adheres to the above conditions. ## Column ID diff --git a/specification/glossary.md b/specification/glossary.md index 70f761ea9..c09626a3f 100644 --- a/specification/glossary.md +++ b/specification/glossary.md @@ -52,7 +52,7 @@ A customer's agreement to consume a specific quantity of a service or resource o A billing discount model that offers reduced rates on preselected SKUs in exchange for an obligated usage or spend amount over a predefined term. Commitment discount purchases, made upfront and/or with recurring monthly payments are amortized evenly across predefined charge periods (i.e. hourly), and unused amounts cannot be carried over to subsequent charge periods. Commitment discounts are publicly available to customers without special contract arrangements. -Commitment Flexibility +Commitment Discount Flexibility A feature of [*commitment discounts*](#glossary:commitment-discount) that may further transform the predetermined amount of usage purchased or consumed based on additional, provider-specific requirements. diff --git a/supporting_content/columns/effectivecost.md b/supporting_content/columns/effectivecost.md index 0364fe0e0..248eb57a4 100644 --- a/supporting_content/columns/effectivecost.md +++ b/supporting_content/columns/effectivecost.md @@ -42,7 +42,7 @@ ___ | Jan 4 2023 - Jan 5 2023 | Jan 1 2023 - Jan 31 2023 | OD Usage | 1 | 0 | 2.542465753 | | Jan 4 2023 - Jan 5 2023 | Jan 1 2023 - Jan 31 2023 | Unused RI Usage | 2 | 0 | 1.271232877 | -*Note: For the Reserved Instance Usage the Billed cost is zero as this RI is full upfront. It is especially important to note that the usage units must be normalized for this formula to be applicable in cases of size flexibility (e.g. c7g.large normalized units is 4, c7g.medium is 2). Effective cost is the same as amortization because the upfront fee covers all of the compute usage expense for this row.* +*Note: For the Reserved Instance Usage the Billed cost is zero as this RI is full upfront. It is especially important to note that the usage units must be normalized for this formula to be applicable in cases of commitment discount flexibility (e.g. c7g.large normalized units is 4, c7g.medium is 2). Effective cost is the same as amortization because the upfront fee covers all of the compute usage expense for this row.* ### Example usage scenarios From 6dfa91f81e994fdd06d9b8e771e6f9588e508585 Mon Sep 17 00:00:00 2001 From: Michael Flanakin Date: Thu, 26 Sep 2024 21:58:56 -0700 Subject: [PATCH 35/52] FOCUS 1.1 changelog updates (#548) Changelog updates for FOCUS 1.1 --------- Co-authored-by: Joaquin Co-authored-by: Christopher Harris Co-authored-by: Udam Dewaraja --- CHANGELOG.md | 77 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 72 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 96131dca2..90c970c37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,13 +5,60 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## v1.1 + +Announced November 2024 + +**Added:** + +- `CapacityReservationId` column +- `CapacityReservationStatus` column +- `CommitmentDiscountQuantity` column +- `CommitmentDiscountUnit` column +- `ServiceSubcategory` column +- `SkuMeter` column +- `SkuPriceDetails` column +- `ProviderVersion` metadata schema property + +**Changed:** + +- `CommitmentDiscountId` column updates: + - Must be globally unique within the provider. + - Should be a fully-qualified identifier. +- `ConsumedQuantity` column updates: + - Must be null when `CommitmentDiscountStatus` is "Unused". +- `ConsumedUnit` column updates: + - Must be null when `ChargeClass` is not "Correction" and `ChargeCategory` is not "Usage". + - Must be null when `ChargeClass` is not "Correction" and `ChargeCategory` is "Usage" and `CommitmentDiscountStatus` is "Unused". + - May be null when `ChargeCategory` is "Usage" and `ChargeClass` is "Correction". +- `EffectiveCost` column updates: + - When `CommitmentDiscountStatus` is "Unused", must be the difference between the used commitment discount amount and the portion of the total commitment discount purchase applicable for the charge period. +- `PricingCategory` column updates: + - Must not be "Committed" when the charge is for a commitment discount purchase. +- `SkuPriceId` column updates: + - `SkuId` can be used if the provider does not have a `SkuPriceId` but other requirements must be met. +- Metadata updates: + - Must be provided in the defined metadata schema. + - Must be an object. + - Must not be null. + - Must include a reference to the schema of the data. + - Schema reference must not be in the FOCUS dataset itself. + - Must be an accurate and complete representation of the provided FOCUS dataset. + - Metadata implementation should be publicly documented. +- `SchemaId` metadata schema property updates: + - Recommended to be a globally unique identifier (GUID) instead of a universally unique identifier (UUID) or SemVer version. + +[All 1.1 changes](https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/compare/v1.0...v1.1-cr) + +
+ ## v1.0 Announced June 20, 2024 @@ -25,6 +72,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), - `ContractedUnitPrice` column - `RegionId` column - `RegionName` column +- `DataGenerator` metadata property +- `CreationDate` metadata schema property +- `FocusVersion` metadata schema property +- `SchemaId` metadata schema property +- `ColumnName` metadata column definition property +- `DataType` metadata column definition property +- `NumberScale` metadata column definition property +- `NumberPrecision` metadata column definition property +- `ProviderTagPrefix` metadata column definition property +- `StringEncoding` metadata column definition property +- `StringMaxLength` metadata column definition property **Changed:** @@ -104,7 +162,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), - `ChargeSubcategory` column - See `ChargeCategory` and `ChargeClass` columns -[All 1.0 changes](https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/compare/v1.0-preview-cr...1.0-cr) +[All 1.0 changes](https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/compare/v1.0-preview...v1.0)
@@ -147,14 +205,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), - `AmortizedCost` column renamed to `EffectiveCost` - `ChargeType` column renamed to `ChargeCategory` -[All 1.0-preview changes](https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/compare/v0.5-cr...v1.0-preview-cr) +[All 1.0-preview changes](https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/compare/v0.5...v1.0-preview)
## v0.5 + Announced June 24, 2023 **Added:** + - `Column naming convention` attribute - `Currency code format` attribute - `Date/time format` attribute @@ -181,7 +241,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), - `SubAccountId` column - `SubAccountName` column -[All 0.5 changes](https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/compare/7106bbe...v0.5-cr) +[All 0.5 changes](https://github.com/FinOps-Open-Cost-and-Usage-Spec/FOCUS_Spec/compare/7106bbe...v0.5)
@@ -199,6 +259,8 @@ This table maps the evolution of the specification, showcasing column introducti | BillingCurrency | 0.5 | | | BillingPeriodEnd | 0.5 | | | BillingPeriodStart | 0.5 | | +| CapacityReservationId | 1.1 | | +| CapacityReservationStatus | 1.1 | | | ChargeType | 0.5 | Renamed to ChargeCategory in v1.0-preview | | ChargeCategory | 1.0-preview | Renamed from ChargeType in v1.0-preview | | ChargeClass | 1.0 | | @@ -212,6 +274,8 @@ This table maps the evolution of the specification, showcasing column introducti | CommitmentDiscountName | 1.0-preview | | | CommitmentDiscountStatus | 1.0 | | | CommitmentDiscountType | 1.0-preview | | +| CommitmentDiscountQuantity | 1.1 | | +| CommitmentDiscountUnit | 1.1 | | | ConsumedQuantity | 1.0 | Renamed from UsageQuantity in v1.0 | | ConsumedUnit | 1.0 | Renamed from UsageUnit in v1.0 | | ContractedCost | 1.0 | | @@ -233,7 +297,10 @@ This table maps the evolution of the specification, showcasing column introducti | ResourceType | 1.0-preview | | | ServiceCategory | 0.5 | | | ServiceName | 0.5 | | +| ServiceSubcategory | 1.1 | | | SkuId | 1.0-preview | | +| SkuMeter | 1.1 | | +| SkuPriceDetails | 1.1 | | | SkuPriceId | 1.0-preview | | | SubAccountId | 0.5 | | | SubAccountName | 0.5 | | From 9e0f320d433b66dcc24669db56632e32d736a3bc Mon Sep 17 00:00:00 2001 From: Shawn Alpay <77511110+shawnalpay@users.noreply.github.com> Date: Fri, 27 Sep 2024 08:48:12 -0700 Subject: [PATCH 36/52] Repaired the table format in supporting content for SubaccountID (#558) Someone in the FOCUS User Group was asking about Resource Group, and I pointed them to the supporting content for SubaccountID. There, I noticed that the table format was broken. I just repaired it. Co-authored-by: Shawn Alpay <77511110+salpaysenturus@users.noreply.github.com> Co-authored-by: Joaquin --- supporting_content/columns/subaccountid.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/supporting_content/columns/subaccountid.md b/supporting_content/columns/subaccountid.md index dd3a6f74f..6c470a27c 100644 --- a/supporting_content/columns/subaccountid.md +++ b/supporting_content/columns/subaccountid.md @@ -32,8 +32,8 @@ Current values observed in billing data for various scenarios: FOCUS plans to include Level 1, Level 3 in the specification. Level 5 (resource name, resource id) are already in the specification. | Provider | Level 1 | Level 2 | Level 3 | Level 4 | Level 5 | | -| | Billing Account | Sub Account Group (optional) | Sub Account | | | | |----------|---------|---------|---------|---------|---------|---------| +| | Billing Account | Sub Account Group (optional) | Sub Account | | | | | AWS | Management Account | Org | Account | Resource Group (optional) | Resource | | | GCP | Billing Account | Folder | Project | | | | | MS EA | Billing Account (Invoice Scope) | Department | Enrollment Account | Subscription | Resource Group | Resource | From b621a1c6aabdf5e79a7fb4f45381840f560f5189 Mon Sep 17 00:00:00 2001 From: Udam Dewaraja Date: Thu, 3 Oct 2024 16:29:32 -0700 Subject: [PATCH 37/52] Cleanup Metadata PR to fix content bugs/errors, broken links, reduce nesting, formatting (#543) Fixes include fixing missing content linking, broken links, formatting, and some content bugs. --- specification/Makefile | 6 ++++ .../appendix/commitment_discounts.md | 30 +++++++++---------- specification/appendix/examples/examples.mdpp | 2 +- .../metadata/data_generator_example.md | 20 ------------- .../examples/metadata/metadata_examples.mdpp | 24 --------------- .../adding_new_columns_example.md | 10 +++---- .../changing_column_metadata_example.md | 12 ++++---- .../correcting_schema_errors_example.md | 11 ++++--- .../data_generator_example.md | 18 +++++++++++ .../focus_version_changed_example.md | 12 ++++---- ...nged_with_provider_version_used_example.md | 28 +++++++---------- .../metadata_examples/metadata_examples.mdpp | 24 +++++++++++++++ .../provider_version_changed_example.md | 15 ++++------ .../removing_columns_example.md | 10 +++---- .../schema_metadata_example.md | 10 +++---- .../schema_metadata_reference_example.md | 14 ++++----- .../data_generator/data_generator.mdpp | 2 +- specification/metadata/schema/schema.mdpp | 17 +++++------ 18 files changed, 122 insertions(+), 143 deletions(-) delete mode 100644 specification/appendix/examples/metadata/data_generator_example.md delete mode 100644 specification/appendix/examples/metadata/metadata_examples.mdpp rename specification/appendix/examples/{metadata => metadata_examples}/adding_new_columns_example.md (80%) rename specification/appendix/examples/{metadata => metadata_examples}/changing_column_metadata_example.md (83%) rename specification/appendix/examples/{metadata => metadata_examples}/correcting_schema_errors_example.md (79%) create mode 100644 specification/appendix/examples/metadata_examples/data_generator_example.md rename specification/appendix/examples/{metadata => metadata_examples}/focus_version_changed_example.md (71%) rename specification/appendix/examples/{metadata => metadata_examples}/focus_version_changed_with_provider_version_used_example.md (80%) create mode 100644 specification/appendix/examples/metadata_examples/metadata_examples.mdpp rename specification/appendix/examples/{metadata => metadata_examples}/provider_version_changed_example.md (69%) rename specification/appendix/examples/{metadata => metadata_examples}/removing_columns_example.md (86%) rename specification/appendix/examples/{metadata => metadata_examples}/schema_metadata_example.md (76%) rename specification/appendix/examples/{metadata => metadata_examples}/schema_metadata_reference_example.md (63%) diff --git a/specification/Makefile b/specification/Makefile index 0465221a0..253b32424 100644 --- a/specification/Makefile +++ b/specification/Makefile @@ -25,7 +25,13 @@ else endif ./validate_includes.py columns ./validate_includes.py attributes + ./validate_includes.py metadata + ./validate_includes.py metadata/data_generator + ./validate_includes.py metadata/schema + ./validate_includes.py metadata/schema/column_definition ./validate_includes.py appendix + ./validate_includes.py appendix/examples + ./validate_includes.py appendix/examples/metadata_examples PYTHONPATH=../vendored/ $(MARKDOWNPP) spec.mdpp -o $@ $(PYMARKDOWNLNT) --config markdownlnt.cfg scan $(SPEC_SOURCE_MDFILES) $(PYMARKDOWNLNT) --config markdownlnt.cfg scan $@ diff --git a/specification/appendix/commitment_discounts.md b/specification/appendix/commitment_discounts.md index ce9b079dd..6f83a618f 100644 --- a/specification/appendix/commitment_discounts.md +++ b/specification/appendix/commitment_discounts.md @@ -14,16 +14,16 @@ While customers are bound to the *term* of a *commitment discounts*, providers o * *No Upfront* - The *commitment discounts* is paid on a repeated basis, typically over each [*billing period*](glossary:billing-period) of the *term*. * *Partial Upfront* - Some of the *commitment discounts* is paid before the *term* begins, and the rest is paid repeatedly over the *term*. -For example, if a customer buys a 1-year, spend-based *commitment discount* with a $1.00 hourly commit and pays with the partial option, the *commitment discount's* payment consists of a one-time purchase in the beginning of the *term* *and* monthly recurring purchases with the following totals: +For example, if a customer buys a 1-year, spend-based *commitment discount* with a $1.00 hourly commit and pays with the partial option, the *commitment discount's* payment consists of a one-time purchase in the beginning of the *term* *and* monthly recurring purchases with the following totals: -1. *One-Time* - $4,380 (`24 hours * 365 days * $1.00 * 0.5`) -2. *Recurring* - $182.50 (`24 hours * 365 days * $1.00 / 12 months`) +1. *One-Time* - $4,380 (`24 hours * 365 days * $1.00 * 0.5`) +2. *Recurring* - $182.50 (`24 hours * 365 days * $1.00 / 12 months`) ## Usage Commitment discounts follow a "use-it-or-lose-it" model where the [*amortization*](glossary:amortization) of a *commitment discount's* purchase applies evenly to eligible *resources* over each [*charge period*](glossary:charge-period) of the *term*. -For example, if a customer buys a spend-based *commitment discount* with a $1.00 hourly commit in January (31 days), only $1.00 is eligible for consumption for each hourly *charge period*. If a customer has eligible *resources* running during this *charge period*, an amount of up to $1.00 will be allocated to these *resources*. Conversely, if a customer does have eligible *resources* running that fully take advantage of this $1.00 during this *charge period*, then some or all of this amount will go to waste. +For example, if a customer buys a spend-based *commitment discount* with a $1.00 hourly commit in January (31 days), only $1.00 is eligible for consumption for each hourly *charge period*. If a customer has eligible *resources* running during this *charge period*, an amount of up to $1.00 will be allocated to these *resources*. Conversely, if a customer does have eligible *resources* running that fully take advantage of this $1.00 during this *charge period*, then some or all of this amount will go to waste. ## Commitment Discounts in FOCUS @@ -35,11 +35,11 @@ All *commitment discount* purchases appear with a positive `BilledCost`, `Pricin Recurring purchases are allocated across all corresponding *charge periods* of the *term* when `ChargeCategory` is "Purchase", `ChargeFrequency` is "Recurring", and `CommitmentDiscountQuantity` and `CommitmentDiscountUnit` are reflected only for that *charge period*. -Using the same *commitment discount* example as above with a one-year, spend-based *commitment discount* with a $1.00 hourly commit purchased on Jan 1, 2023, various purchase options are available: +Using the same *commitment discount* example as above with a one-year, spend-based *commitment discount* with a $1.00 hourly commit purchased on Jan 1, 2023, various purchase options are available: #### Scenario #1: All Upfront -The entire *commitment discount* is billed _once_ during the first *charge period* of the *term* for $8,670 (derived as `24 hours * 365 days * $1.00`). +The entire *commitment discount* is billed _once_ during the first *charge period* of the *term* for $8,670 (derived as `24 hours * 365 days * $1.00`). ```json [ @@ -63,7 +63,7 @@ The entire *commitment discount* is billed _once_ during the first *charge perio #### Scenario #2: No Upfront -The *commitment discount* is billed across all 8,760 (`24 hours * 365 days`) *charge periods* of the *term* with $1.00 allocated to each *charge period* over the *term*. +The *commitment discount* is billed across all 8,760 (`24 hours * 365 days`) *charge periods* of the *term* with $1.00 allocated to each *charge period* over the *term*. ```json [ @@ -89,7 +89,7 @@ The *commitment discount* is billed across all 8,760 (`24 hours * 365 days`) *ch #### Scenario #3: Partial Upfront -With a 50/50 split, half of the commitment is billed _once_ during the first *charge period* of the *term* for $4,380 (derived as `24 hours * 182.5 days * $1.00`), and the other half is billed across each *charge period* over the term, derived as (`$1.00 * 8,760 hours * 0.5`). Amortized costs incur half of the amount (i.e. $0.50) from the one-time purchase and the other half from the recurring purchase. +With a 50/50 split, half of the commitment is billed _once_ during the first *charge period* of the *term* for $4,380 (derived as `24 hours * 182.5 days * $1.00`), and the other half is billed across each *charge period* over the term, derived as (`$1.00 * 8,760 hours * 0.5`). Amortized costs incur half of the amount (i.e. $0.50) from the one-time purchase and the other half from the recurring purchase. ```json [ @@ -130,16 +130,16 @@ With a 50/50 split, half of the commitment is billed _once_ during the first *ch ### Usage *Rows* -*Amortization* of *commitment discounts* occur similarly regardless of how *commitment discount* purchases are made. The same usage-based or spend-based amount is applied evenly across all *charge periods* and potentially allocated to eligible *resources*. Continuing with the same *commitment discount* example, a one-year, spend-based *commitment discount* with a $1.00 hourly commit and 1 *resource* (for simplicity) yields 4 types of scenarios that can occur during a *charge period*: +*Amortization* of *commitment discounts* occur similarly regardless of how *commitment discount* purchases are made. The same usage-based or spend-based amount is applied evenly across all *charge periods* and potentially allocated to eligible *resources*. Continuing with the same *commitment discount* example, a one-year, spend-based *commitment discount* with a $1.00 hourly commit and 1 *resource* (for simplicity) yields 4 types of scenarios that can occur during a *charge period*: * Scenario #1: An eligible *resource* fully consumes the allocated amount (100% utilization) * Scenario #2: No eligible *resource* consumes the allocated amount (0% utilization) * Scenario #3: An eligible *resource* partially consumes the allocated amount (75% utilization) -* Scenario #4: An eligible *resource* fully consumes the $1.00 hourly commit with an overage (100% utilization + overage) +* Scenario #4: An eligible *resource* fully consumes the $1.00 hourly commit with an overage (100% utilization + overage) #### Scenario #1: An eligible *resource* fully consumes the allocated amount (100% utilization) -In this scenario, one eligible *resource* runs for the full hour and consumes $1.00, so one *row* allocated to the *resource* is produced. +In this scenario, one eligible *resource* runs for the full hour and consumes $1.00, so one *row* allocated to the *resource* is produced. ```json [ @@ -166,7 +166,7 @@ In this scenario, one eligible *resource* runs for the full hour and consumes $1 #### Scenario #2: No eligible *resource* consumes the allocated amount (0% utilization) -In this situation, the full eligible, $1.00 amount remained unutilized and results in 1 unused *row*. In this scenario, it is important to note that while `CommitmentDiscountQuantity` is not because $1 was still drawn down by the *commitment discount* even though, no *resource* was allocated, so `ConsumedQuantity` and `ConsumedUnit` are null. +In this situation, the full eligible, $1.00 amount remained unutilized and results in 1 unused *row*. In this scenario, it is important to note that while `CommitmentDiscountQuantity` is not because $1 was still drawn down by the *commitment discount* even though, no *resource* was allocated, so `ConsumedQuantity` and `ConsumedUnit` are null. ```json [ @@ -193,7 +193,7 @@ In this situation, the full eligible, $1.00 amount remained unutilized and resul #### Scenario #3: An eligible *resource* partially consumes the allocated amount (75% utilization) -In this scenario, one eligible *resource* runs for the full hour and consumes $0.75 of the $1.00 allocation. One *row* shows $0.75 to a *resource*, and the other *row* shows that $0.25 was unused. +In this scenario, one eligible *resource* runs for the full hour and consumes $0.75 of the $1.00 allocation. One *row* shows $0.75 to a *resource*, and the other *row* shows that $0.25 was unused. ```json [ @@ -236,9 +236,9 @@ In this scenario, one eligible *resource* runs for the full hour and consumes $0 ] ``` -#### Scenario #4: An eligible *resource* fully consumes the $1.00 hourly commit with an overage (100% utilization + overage) +#### Scenario #4: An eligible *resource* fully consumes the $1.00 hourly commit with an overage (100% utilization + overage) -In this scenario, one eligible *resource* runs for the full hour and is charged $1.50. One *row* shows that $1.00 was *amortized* from the *commitment discount*, and the other shows that $0.50 was charged as standard, on-demand spend. +In this scenario, one eligible *resource* runs for the full hour and is charged $1.50. One *row* shows that $1.00 was *amortized* from the *commitment discount*, and the other shows that $0.50 was charged as standard, on-demand spend. ```json [ diff --git a/specification/appendix/examples/examples.mdpp b/specification/appendix/examples/examples.mdpp index edf59c82a..1d217f201 100644 --- a/specification/appendix/examples/examples.mdpp +++ b/specification/appendix/examples/examples.mdpp @@ -2,4 +2,4 @@ *This section is non-normative.* -!INCLUDE "metadata/metadata_examples.mdpp",1 +!INCLUDE "metadata_examples/metadata_examples.mdpp",1 diff --git a/specification/appendix/examples/metadata/data_generator_example.md b/specification/appendix/examples/metadata/data_generator_example.md deleted file mode 100644 index 932e52bb4..000000000 --- a/specification/appendix/examples/metadata/data_generator_example.md +++ /dev/null @@ -1,20 +0,0 @@ -# Data Generator Metadata - -## Scenario - -Acme provides metadata about the data generator. They provide this via the Data Generator schema object. - -## Supplied Metadata - -## Location of Data Generator Metadata File - -`/FOCUS/metadata/data_generator.json` - -## Content of Data Generator Metadata File - -```json -{ - "DataGenerator": "Acme" -} -``` - diff --git a/specification/appendix/examples/metadata/metadata_examples.mdpp b/specification/appendix/examples/metadata/metadata_examples.mdpp deleted file mode 100644 index 58d75735d..000000000 --- a/specification/appendix/examples/metadata/metadata_examples.mdpp +++ /dev/null @@ -1,24 +0,0 @@ -# Metadata Examples - -The following is an example metadata JSON structure provided by a hypothetical FOCUS data provider called ACME. This example illustrates an example of how a provider can supply the required reference between the FOCUS data and the schema metadata. Provider implementations will vary on how the metadata is stored and retrieved; however, the provider's chosen metadata delivery approach should be able to support the structure represented in this example. - -## Scenario - -In this example, the provider supports delivery of FOCUS data via file export to a data storage system. The provider delivers data every 12 hours. - -## Example Data Structure - -* export root location: `/FOCUS` -* metadata location: `/FOCUS/metadata` -* focus data location: `/FOCUS/data` - -!INCLUDE "data_generator_example.md",1 -!INCLUDE "schema_metadata_example.md",1 -!INCLUDE "schema_metadata_reference_example.md",1 -!INCLUDE "adding_new_columns_example.md",1 -!INCLUDE "removing_columns_example.md",1 -!INCLUDE "changing_a_columns_metadata_example.md", -!INCLUDE "correcting_schema_error_example.md",1 -!INCLUDE "focus_version_changed_example.md",1 -!INCLUDE "focus_version_changed_with_provider_version_example.md",1 -!INCLUDE "provider_version_changed.md",1 diff --git a/specification/appendix/examples/metadata/adding_new_columns_example.md b/specification/appendix/examples/metadata_examples/adding_new_columns_example.md similarity index 80% rename from specification/appendix/examples/metadata/adding_new_columns_example.md rename to specification/appendix/examples/metadata_examples/adding_new_columns_example.md index ede72f5c8..fb3111dec 100644 --- a/specification/appendix/examples/metadata/adding_new_columns_example.md +++ b/specification/appendix/examples/metadata_examples/adding_new_columns_example.md @@ -2,15 +2,13 @@ ## Scenario -ACME has decided add additional columns to their FOCUS data export. The new columns are x_awesome_column1, x_awesome_column2, and x_awesome_column3. The provider creates a new schema object to represent the new schema, this schema object has a unique SchemaId. The subsequent data exports that use the new schema include the new schema's id as a reference to their corresponding schema object. +ACME has decided add additional columns to their FOCUS data export. The new columns are x_awesome_column1, x_awesome_column2, and x_awesome_column3. The provider creates a new [Schema](#schema) object to represent the new schema, this schema object has a unique [SchemaId](#schemaid). The subsequent data exports that use the new schema include the new schema's id as a reference to their corresponding schema object. ## Supplied Metadata -## Location for the new schema object +Metadata can be provided at a location such as `/FOCUS/metadata/schemas/schema-23456-abcde-23456-abcde-23456.json`. -`/FOCUS/metadata/schemas/schema-23456-abcde-23456-abcde-23456.json` - -## Content for the new schema object +The updated schema related metadata could look like this: ```json { @@ -75,4 +73,4 @@ ACME has decided add additional columns to their FOCUS data export. The new colu } ``` -For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](../schema_metadata_reference_example.md) +For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](#schemametadatatofocusdatareference) diff --git a/specification/appendix/examples/metadata/changing_column_metadata_example.md b/specification/appendix/examples/metadata_examples/changing_column_metadata_example.md similarity index 83% rename from specification/appendix/examples/metadata/changing_column_metadata_example.md rename to specification/appendix/examples/metadata_examples/changing_column_metadata_example.md index 85d65e9f9..7e2bb1687 100644 --- a/specification/appendix/examples/metadata/changing_column_metadata_example.md +++ b/specification/appendix/examples/metadata_examples/changing_column_metadata_example.md @@ -1,16 +1,14 @@ -# Changing a Column's Metadata Example +# Changing Column Metadata ## Scenario -ACME has decided to change the datatype of column x_awesome_column1 from a string to a number. ACME creates a new schema object with the modification to x_awesome_column2. +ACME has decided to change the datatype of column x_awesome_column1 from a string to a number. ACME creates a new [Schema](#schema) object with the modification to x_awesome_column2. ## Supplied Metadata -## Location for the new schema object +Metadata can be provided at a location such as `/FOCUS/metadata/schemas/schema-67891-abcde-67891-abcde-67891.json`. -`/FOCUS/metadata/schemas/schema-67891-abcde-67891-abcde-67891.json` - -## Content for the new schema object +The updated schema related metadata could look like this: ```json { @@ -69,4 +67,4 @@ ACME has decided to change the datatype of column x_awesome_column1 from a strin } ``` -For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](schema_metadata_reference_example.md) +For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](#schemametadatatofocusdatareference) diff --git a/specification/appendix/examples/metadata/correcting_schema_errors_example.md b/specification/appendix/examples/metadata_examples/correcting_schema_errors_example.md similarity index 79% rename from specification/appendix/examples/metadata/correcting_schema_errors_example.md rename to specification/appendix/examples/metadata_examples/correcting_schema_errors_example.md index 16d166c3b..1248e7c24 100644 --- a/specification/appendix/examples/metadata/correcting_schema_errors_example.md +++ b/specification/appendix/examples/metadata_examples/correcting_schema_errors_example.md @@ -1,16 +1,14 @@ -# Provider has an error in their schema metadata +# Provider Metadata Error Correction ## Scenario -ACME has discovered that while their export includes the column x_awesome_column3, the schema metadata does not include this column. In this case, the provider fixes the metadata in existing the schema object and does not need to create a new schema object. Reference metadata remains the same. +ACME has discovered that while their export includes the column x_awesome_column3, the [Schema](#schema) metadata does not include this column. In this case, the provider fixes the metadata in the existing schema object and does not need to create a new schema object. Reference metadata remains the same. ## Supplied Metadata -## Location of the schema object +Metadata can be provided at a location such as `/FOCUS/metadata/schemas/schema-34567-abcde-34567-abcde-34567.json`. -`/FOCUS/metadata/schemas/schema-34567-abcde-34567-abcde-34567.json` - -## Content of the schema object +The updated schema related metadata could look like this: ```json { @@ -70,3 +68,4 @@ ACME has discovered that while their export includes the column x_awesome_column ] } ``` + diff --git a/specification/appendix/examples/metadata_examples/data_generator_example.md b/specification/appendix/examples/metadata_examples/data_generator_example.md new file mode 100644 index 000000000..62f03e9e3 --- /dev/null +++ b/specification/appendix/examples/metadata_examples/data_generator_example.md @@ -0,0 +1,18 @@ +# Data Generator Metadata + +## Scenario + +Acme provides metadata about the data generator as a part of their FOCUS data export. They provide the relevant data via the [Data Generator](#datagenerator) schema object. + +## Supplied Metadata + +Metadata can be provided at a location such as `/FOCUS/metadata/data_generator.json`. + +The updated data generator related metadata could look like this: + +```json +{ + "DataGenerator": "Acme" +} +``` + diff --git a/specification/appendix/examples/metadata/focus_version_changed_example.md b/specification/appendix/examples/metadata_examples/focus_version_changed_example.md similarity index 71% rename from specification/appendix/examples/metadata/focus_version_changed_example.md rename to specification/appendix/examples/metadata_examples/focus_version_changed_example.md index 31a28b8ce..d684e31e6 100644 --- a/specification/appendix/examples/metadata/focus_version_changed_example.md +++ b/specification/appendix/examples/metadata_examples/focus_version_changed_example.md @@ -1,16 +1,14 @@ -# Provider has an error in their schema metadata +# FOCUS Version Changed ## Scenario -ACME's previous exports used Focus Version 1.0. They are now going to adopt Focus Version 1.1. It is required that they create a new schema metadata object when using a new FOCUS version regardless of schema changes. In this example, the FOCUS new version adoption doesn't include columns changes. This is to illustrate that FOCUS Version changes are independent of column changes, however, this scenario is unlikely. +ACME's previous exports used FOCUS version 1.0. They are now going to adopt FOCUS version 1.1. It is required that they create a new schema metadata object which specifies the new FOCUS version via the [FOCUS Version](#focusversion) property - regardless of schema changes. In this example, the new FOCUS version adoption doesn't include columns changes. This is to illustrate that FOCUS version changes are independent of column changes, however, this scenario is unlikely. ## Supplied Metadata -## Location of the new schema object +Metadata can be provided at a location such as `/FOCUS/metadata/schemas/schema-45678-abcde-45678-abcde-45678.json`. -`/FOCUS/metadata/schemas/schema-45678-abcde-45678-abcde-45678.json` - -## Content of the schema object +The updated schema related metadata could look like this: ```json { @@ -69,4 +67,4 @@ ACME's previous exports used Focus Version 1.0. They are now going to adopt Focu } ``` -For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](schema_metadata_reference_example.md) +For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](#schemametadatatofocusdatareference) diff --git a/specification/appendix/examples/metadata/focus_version_changed_with_provider_version_used_example.md b/specification/appendix/examples/metadata_examples/focus_version_changed_with_provider_version_used_example.md similarity index 80% rename from specification/appendix/examples/metadata/focus_version_changed_with_provider_version_used_example.md rename to specification/appendix/examples/metadata_examples/focus_version_changed_with_provider_version_used_example.md index bf166cfa3..536a4a1b0 100644 --- a/specification/appendix/examples/metadata/focus_version_changed_with_provider_version_used_example.md +++ b/specification/appendix/examples/metadata_examples/focus_version_changed_with_provider_version_used_example.md @@ -2,23 +2,22 @@ ## Scenario -ACME uses Provider Version, and their previous exports used FOCUS Version 1.0. Their current Provider Version is 2.2. They are now going to adopt FOCUS Version 1.1. Because it is required that they update their Provider Version when using a new FOCUS Version, they create a new schema object designating that both have changed. In this example, the adoption of the new FOCUS Version doesn't include additional columns. This is to illustrate that Provider Version changes are independent of column changes; however, this scenario is unlikely. +ACME specifies the optional metadata property [Provider Version](#providerversion) in their [Schema](#schema) object. Their provider version 2.2 supported FOCUS version 1.0. They are now going to adopt FOCUS Version 1.1 which requires that they update their Provider Version when updating the FOCUS Version. They create a new schema object designating that both properties have changed. In this example, the adoption of the new FOCUS version doesn't include additional columns. This is to illustrate that Provider Version can change independent of column changes; however, this scenario is unlikely. The provider creates a new schema object to represent the new schema. The provider includes both the new FOCUS Version and Provider Version in the schema object. ## Supplied Metadata -## Location of the previous schema object +Metadata can be provided at a location such as `/FOCUS/metadata/schemas/schema-45678-abcde-45678-abcde-45678.json`. -`/FOCUS/metadata/schemas/schema-34567-abcde-34567-abcde-34567.json` - -## Content of the previous schema object +The updated schema related metadata could look like this: ```json { - "SchemaId": "34567-abcde-34567-abcde-34567", + "SchemaId": "45678-abcde-45678-abcde-45678", "FocusVersion": "1.1", - "ProviderVersion": "2.2", + "ProviderVersion": "2.3", + "name": "New Columns", "CreationDate": "2024-04-02T12:01:03.083z", "ColumnDefinition": [ { @@ -72,18 +71,13 @@ The provider creates a new schema object to represent the new schema. The provid } ``` -## Location of the new schema object - -`/FOCUS/metadata/schemas/schema-45678-abcde-45678-abcde-45678.json` - -## Content of the new schema object +For reference, the prior schema object looked like this: ```json { - "SchemaId": "45678-abcde-45678-abcde-45678", - "FocusVersion": "1.1", - "ProviderVersion": "2.3", - "name": "New Columns", + "SchemaId": "34567-abcde-34567-abcde-34567", + "FocusVersion": "1.0", + "ProviderVersion": "2.2", "CreationDate": "2024-04-02T12:01:03.083z", "ColumnDefinition": [ { @@ -137,4 +131,4 @@ The provider creates a new schema object to represent the new schema. The provid } ``` -For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](schema_metadata_reference_example.md) +For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](#schemametadatatofocusdatareference) diff --git a/specification/appendix/examples/metadata_examples/metadata_examples.mdpp b/specification/appendix/examples/metadata_examples/metadata_examples.mdpp new file mode 100644 index 000000000..eae6ee5f2 --- /dev/null +++ b/specification/appendix/examples/metadata_examples/metadata_examples.mdpp @@ -0,0 +1,24 @@ +# Metadata Examples + +The following sections contain examples of metadata provided by a hypothetical FOCUS data provider called ACME to supply the required reference between the FOCUS dataset and the schema metadata. Provider implementations will vary on how the metadata is disseminated; however, the provider's chosen metadata delivery approach should be able to support the structure represented in this example. + +In this example, the provider supports delivery of FOCUS data via file export to a data storage system. It uses JSON as the format for providing the metadata. The provider delivers data every 12 hours into a path structure described below: + +| Type of data | Path | +|:--------------------|:------------------| +| Export location | `/FOCUS` | +| Metadata location | `/FOCUS/metadata` | +| Cost data location | `/FOCUS/data` | + +Here are some metadata examples for various scenarios: + +!INCLUDE "data_generator_example.md",1 +!INCLUDE "schema_metadata_example.md",1 +!INCLUDE "schema_metadata_reference_example.md",1 +!INCLUDE "adding_new_columns_example.md",1 +!INCLUDE "removing_columns_example.md",1 +!INCLUDE "changing_column_metadata_example.md",1 +!INCLUDE "correcting_schema_errors_example.md",1 +!INCLUDE "focus_version_changed_example.md",1 +!INCLUDE "focus_version_changed_with_provider_version_used_example.md",1 +!INCLUDE "provider_version_changed_example.md",1 diff --git a/specification/appendix/examples/metadata/provider_version_changed_example.md b/specification/appendix/examples/metadata_examples/provider_version_changed_example.md similarity index 69% rename from specification/appendix/examples/metadata/provider_version_changed_example.md rename to specification/appendix/examples/metadata_examples/provider_version_changed_example.md index 530e56ca7..ed912bacf 100644 --- a/specification/appendix/examples/metadata/provider_version_changed_example.md +++ b/specification/appendix/examples/metadata_examples/provider_version_changed_example.md @@ -1,19 +1,16 @@ -# FOCUS Version Changed by Provider Using Provider Version +# Data Changed by Provider Using Provider Version ## Scenario -ACME uses provider version, and they made a change to their approach to create FOCUS data that does not adopt a new FOCUS Version, nor make a change the included columns but does impact values in the data. This is to illustrate that Provider Version changes are independent of column changes, however provider version changes may include column changes. +ACME specifies the optional metadata property [Provider Version](#providerversion) in their [Schema](#schema) object. They made a change to the FOCUS dataset they produce that does not adopt a new FOCUS Version, nor make a change the included columns but does impact values in the data. This example illustrates that Provider Version changes are independent of column changes, however provider version changes may include column changes. -The provider creates a new schema object to represent the new schema. The provider includes both the new FOCUS Version and Provider Version in the schema object. +The provider creates a new schema object to represent the new schema. The provider includes both the FOCUS Version and Provider Version in the schema object. ## Supplied Metadata -## Location of the new schema object +Metadata can be provided at a location such as `/FOCUS/metadata/schemas/schema-56789-abcde-56789-abcde-56789.json`. - -`/FOCUS/metadata/schemas/schema-56789-abcde-56789-abcde-56789.json` - -## Content of the new schema object +The updated schema related metadata could look like this: ```json { @@ -73,4 +70,4 @@ The provider creates a new schema object to represent the new schema. The provid } ``` -For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](schema_metadata_reference_example.md) +For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](#schemametadatatofocusdatareference) diff --git a/specification/appendix/examples/metadata/removing_columns_example.md b/specification/appendix/examples/metadata_examples/removing_columns_example.md similarity index 86% rename from specification/appendix/examples/metadata/removing_columns_example.md rename to specification/appendix/examples/metadata_examples/removing_columns_example.md index b9f47e31e..0b44141cd 100644 --- a/specification/appendix/examples/metadata/removing_columns_example.md +++ b/specification/appendix/examples/metadata_examples/removing_columns_example.md @@ -2,15 +2,13 @@ ## Scenario -ACME has decided to remove columns from their FOCUS data export. The column removed is x_awesome_column3. The provider creates a new schema object to represent the new schema, this schema object has a unique SchemaId. +ACME has decided to remove columns from their FOCUS data export. The column removed is x_awesome_column3. The provider creates a new [Schema](#schema) object to represent the new schema, with a unique [SchemaId](#schemaid). ## Supplied Metadata -## Location for the new schema object +Metadata can be provided at a location such as `/FOCUS/metadata/schemas/schema-34567-abcde-34567-abcde-34567.json`. -`/FOCUS/metadata/schemas/schema-34567-abcde-34567-abcde-34567.json` - -## Content for the new schema object +The updated schema related metadata could look like this: ```json { @@ -69,4 +67,4 @@ ACME has decided to remove columns from their FOCUS data export. The column remo } ``` -For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](schema_metadata_reference_example.md) +For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](#schemametadatatofocusdatareference) diff --git a/specification/appendix/examples/metadata/schema_metadata_example.md b/specification/appendix/examples/metadata_examples/schema_metadata_example.md similarity index 76% rename from specification/appendix/examples/metadata/schema_metadata_example.md rename to specification/appendix/examples/metadata_examples/schema_metadata_example.md index 6a52bda73..8ec30f88e 100644 --- a/specification/appendix/examples/metadata/schema_metadata_example.md +++ b/specification/appendix/examples/metadata_examples/schema_metadata_example.md @@ -1,16 +1,14 @@ -# Schema Metadata Example +# Schema Metadata ## Scenario -ACME has only provided one schema for their provided FOCUS data. ACME provides a directory of schemas and each schema is a single file. Acme's provides a file representing the schema for the data they provide. +ACME has only provided one [Schema](#schema) for their FOCUS data export. ACME provides a directory of schemas and each schema is a single file. Acme's provides a file representing the schema for the data they provide. ## Supplied Metadata -## Location of the schema object +Metadata can be provided at a location such as `/FOCUS/metadata/schemas/schema-1234-abcde-12345-abcde-12345.json`. -`/FOCUS/metadata/schemas/schema-1234-abcde-12345-abcde-12345.json` - -## Content of the schema object +The updated schema related metadata could look like this: ```json { diff --git a/specification/appendix/examples/metadata/schema_metadata_reference_example.md b/specification/appendix/examples/metadata_examples/schema_metadata_reference_example.md similarity index 63% rename from specification/appendix/examples/metadata/schema_metadata_reference_example.md rename to specification/appendix/examples/metadata_examples/schema_metadata_reference_example.md index 9edab82c1..d2ac2aa3b 100644 --- a/specification/appendix/examples/metadata/schema_metadata_reference_example.md +++ b/specification/appendix/examples/metadata_examples/schema_metadata_reference_example.md @@ -2,15 +2,13 @@ ## Scenario -ACME makes a change to the schema of their data exports. For each FOCUS data export, ACME includes a metadata reference to the schema object. Because multiple files are provided, Acme has elected to include a metadata file that includes the focus schema reference that applies to the data export files. They therefore include the new schema id in their export metadata file. +ACME makes a change to the [Schema](#schema) of their data exports. For each FOCUS data export, ACME includes a metadata reference to the schema object. Because multiple files are provided in each export, Acme has elected to include a metadata file in each export folder that includes the FOCUS schema reference that applies to the data export files within that folder. When the schema changes, they include the new [Schema ID](#schemaid) in their export metadata file of the new folder. ## Supplied Metadata -## Location of the existing schema metadata reference file +Metadata can be provided at a location such as `/FOCUS/data/export1-metadata.json` -`/FOCUS/data/export1-metadata.json` - -## Content for the existing export metadata object +The export metadata could look like this: ```json { @@ -41,11 +39,9 @@ ACME makes a change to the schema of their data exports. For each FOCUS data exp } ``` -## Location for the new export metadata object - -`/FOCUS/data/export2-metadata.json` +New metadata can be provided at a location such as `/FOCUS/data/export2-metadata.json`. -## Content for the new export metadata object +The new export metadata could look like this: ```json { diff --git a/specification/metadata/data_generator/data_generator.mdpp b/specification/metadata/data_generator/data_generator.mdpp index 2526c9bc2..f6381353c 100644 --- a/specification/metadata/data_generator/data_generator.mdpp +++ b/specification/metadata/data_generator/data_generator.mdpp @@ -8,6 +8,6 @@ The FOCUS Data Generator metadata MUST be provided. This metadata MUST be of typ ## Schema Example -For an example of the FOCUS Data Generator metadata please refer to: [Data Generator Example](#data_generator_example) +For an example of the FOCUS Data Generator metadata please refer to: [Data Generator Example](#datageneratormetadata) !INCLUDE "datagenerator.md",1 diff --git a/specification/metadata/schema/schema.mdpp b/specification/metadata/schema/schema.mdpp index 7d211016c..50825a4fe 100644 --- a/specification/metadata/schema/schema.mdpp +++ b/specification/metadata/schema/schema.mdpp @@ -15,13 +15,12 @@ It is recommended that the schema reference be provided as an external reference Should the provider change the structure of the supplied FOCUS data artifact, a new schema metadata object MUST be supplied. These scenarios include, but are not limited to: -* [Adding a new column](#adding_new_columns_example) -* [Removing a column](#removing_columns_example) -* [Renaming a column](#renaming_columns_example) -* [Changing column metadata](#changing_column_metadata_example) -* [FOCUS Version is changed](#focus_version_change_example) -* [Provider Version is changed](#provider_version_change_example) -* [Correcting schema metadata errors](#correcting_schema_metadata_errors) +* [Adding a new column](#addingnewcolumns) +* [Removing a column](#removingcolumns) +* [Changing column metadata](#changingcolumnmetadata) +* [FOCUS Version has changed](#focusversionchanged) +* [Provider Version has changed](#schemametadatatofocusdatareference) +* [Correcting schema metadata errors](#providermetadataerrorcorrection) ### Schema Metadata Updates @@ -29,10 +28,10 @@ Should there be an error where the schema metadata object does not match the sch ## Schema Example -For an example of the FOCUS schema metadata please refer to: [Schema Metadata Example](#schema-metadata-examples) +For an example of the FOCUS schema metadata please refer to: [Schema Metadata Example](#schemametadata) !INCLUDE "schemaid.md",1 !INCLUDE "creationdate.md",1 !INCLUDE "focusversion.md",1 -!INCLUDE "providerversion.md", +!INCLUDE "providerversion.md",1 !INCLUDE "column_definition/column_definition.mdpp",1 From 6660a240483e3061f5a19f07fa1db71ab614c89f Mon Sep 17 00:00:00 2001 From: Irena Jurica Date: Fri, 4 Oct 2024 01:42:09 +0200 Subject: [PATCH 38/52] FOCUS #547: Consistency Review - Standardize column specs for correction charges (#549) Standardize the column specifications, i.e. allow nulls in the case of corrections for all columns except cost metrics, and explicitly define value ranges for all metrics, for the following columns: - PricingUnit - ConsumedUnit - CommitmentDiscountUnit - PricingQuantity - ConsumedQuantity - CommitmentDiscountQuantity - ListCost - ContractedCost - ListUnitPrice - ContractedUnitPrice --- ### NOTE: An initial overall analysis of the current correction handling and value ranges was conducted within this PR. Due to deadlines, **the scope of this particular PR was limited to addressing the following two columns**: - **ConsumedUnit** - **ConsumedQuantity** Please use this [table](https://docs.google.com/spreadsheets/d/1SvaD-PSzxwRKExKYbQXbtEmVPtbhN4HnycOatvLfGPI/edit?gid=1823426118#gid=1823426118) to verify the normative requirements. --------- Co-authored-by: Joaquin --- specification/columns/consumedquantity.md | 10 +++++----- specification/columns/consumedunit.md | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/specification/columns/consumedquantity.md b/specification/columns/consumedquantity.md index b7ea4d2d8..b29caa225 100644 --- a/specification/columns/consumedquantity.md +++ b/specification/columns/consumedquantity.md @@ -1,14 +1,14 @@ # Consumed Quantity -The Consumed Quantity represents the volume of a given SKU associated with a metered [*resource*](#glossary:resource) or [*service*](#glossary:service) used, based on the [Consumed Unit](#consumedunit). Consumed Quantity is often derived at a finer granularity or over a different time interval when compared to the [Pricing Quantity](#pricingquantity) (complementary to [Pricing Unit](#pricingunit)) and focuses on metered *resource* and *service* consumption, not pricing and cost. +The Consumed Quantity represents the volume of a metered SKU associated with a [*resource*](#glossary:resource) or [*service*](#glossary:service) used, based on the [Consumed Unit](#consumedunit). Consumed Quantity is often derived at a finer granularity or over a different time interval when compared to the [Pricing Quantity](#pricingquantity) (complementary to [Pricing Unit](#pricingunit)) and focuses on *resource* and *service* consumption, not pricing and cost. The ConsumedQuantity column adheres to the following requirements: * ConsumedQuantity MUST be present in a FOCUS dataset when the provider supports the measurement of usage. * ConsumedQuantity MUST be of type Decimal and MUST conform to [Numeric Format](#numericformat) requirements. -* ConsumedQuantity MUST NOT be null if [ChargeCategory](#chargecategory) is "Usage" and [ChargeClass](#chargeclass) is not "Correction". -* ConsumedQuantity MUST be null if [CommitmentDiscountStatus](#commitmentdiscountstatus) is "Unused" or for other *ChargeCategory* values. -* ConsumedQuantity MAY be negative or null in cases where *ChargeClass* is "Correction". +* ConsumedQuantity MUST NOT be null and MUST be a valid positive decimal value if [ChargeCategory](#chargecategory) is "Usage", [CommitmentDiscountStatus](#commitmentdiscountstatus) is not "Unused", and [ChargeClass](#chargeclass) is not "Correction". +* ConsumedQuantity MAY be null or any valid decimal value if ChargeCategory is "Usage", CommitmentDiscountStatus is not "Unused", and ChargeClass is "Correction". +* ConsumedQuantity MUST be null in all other cases. ## Column ID @@ -20,7 +20,7 @@ Consumed Quantity ## Description -The volume of a given SKU associated with a metered *resource* or *service* used, based on the Consumed Unit. +The volume of a metered SKU associated with a *resource* or *service* used, based on the Consumed Unit. ## Content constraints diff --git a/specification/columns/consumedunit.md b/specification/columns/consumedunit.md index 7fcb4a37a..36d2760f6 100644 --- a/specification/columns/consumedunit.md +++ b/specification/columns/consumedunit.md @@ -1,14 +1,14 @@ # Consumed Unit -The Consumed Unit represents a provider-specified measurement unit indicating how a provider measures usage of a given SKU associated with a metered [*resource*](#glossary:resource) or [*service*](#glossary:service). Consumed Unit complements the [Consumed Quantity](#consumedquantity) metric. It is often listed at a finer granularity or over a different time interval when compared to [Pricing Unit](#pricingunit) (complementary to [Pricing Quantity](#pricingquantity)), and focuses on metered *resource* and *service* consumption, not pricing and cost. +The Consumed Unit represents a provider-specified measurement unit indicating how a provider measures usage of a metered SKU associated with a [*resource*](#glossary:resource) or [*service*](#glossary:service). Consumed Unit complements the [Consumed Quantity](#consumedquantity) metric. It is often listed at a finer granularity or over a different time interval when compared to [Pricing Unit](#pricingunit) (complementary to [Pricing Quantity](#pricingquantity)), and focuses on *resource* and *service* consumption, not pricing and cost. The ConsumedUnit column adheres to the following requirements: * ConsumedUnit MUST be present in the billing data when the provider supports the measurement of usage. * ConsumedUnit MUST be of type String, and the units of measure used in ConsumedUnit SHOULD adhere to the values and format requirements specified in the [UnitFormat](#unitformat) attribute. -* ConsumedUnit MUST NOT be null if [ChargeCategory](#chargecategory) is "Usage" and [ChargeClass](#chargeclass) is not "Correction". -* When *ChargeCategory* is not "Usage", or *ChargeCategory* is "Usage" and [CommitmentDiscountStatus](#commitmentdiscountstatus) is "Unused", ConsumedUnit MUST be null when ChargeClass is not "Correction". -* ConsumedUnit MAY be null if *ChargeCategory* is "Usage" and ChargeClass is "Correction". +* ConsumedUnit MUST NOT be null if [ChargeCategory](#chargecategory) is "Usage", [CommitmentDiscountStatus](#commitmentdiscountstatus) is not "Unused", and [ChargeClass](#chargeclass) is not "Correction". +* ConsumedUnit MAY be null if ChargeCategory is "Usage", CommitmentDiscountStatus is not "Unused", and ChargeClass is "Correction". +* ConsumedUnit MUST be null in all other cases. ## Column ID @@ -20,7 +20,7 @@ Consumed Unit ## Description -Provider-specified measurement unit indicating how a provider measures usage of a given SKU associated with a metered *resource* or *service*. +Provider-specified measurement unit indicating how a provider measures usage of a metered SKU associated with a *resource* or *service*. ## Content constraints From ca924c8c5ed6fcbf7838e0ae7ac005e56662f26c Mon Sep 17 00:00:00 2001 From: Udam Dewaraja Date: Thu, 3 Oct 2024 16:46:37 -0700 Subject: [PATCH 39/52] Service Subcategory language inconsistency fixes (#552) Fixes based on discussions at the consistency review meeting on 9/25. --------- Co-authored-by: Joaquin --- specification/columns/servicesubcategory.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/specification/columns/servicesubcategory.md b/specification/columns/servicesubcategory.md index 82548de45..c353d039f 100644 --- a/specification/columns/servicesubcategory.md +++ b/specification/columns/servicesubcategory.md @@ -2,10 +2,12 @@ The Service Subcategory is a secondary classification of the Service Category for a [*service*](#glossary:service) based on its core function. The Service Subcategory (in conjunction with the Service Category) is commonly used for scenarios like analyzing spend and usage for specific workload types across providers and tracking the migration of workloads across fundamentally different architectures. -* The ServiceSubcategory column MUST be present in a FOCUS dataset and MUST NOT be null. -* This column is of type String and MUST be one of the allowed values. -* Each Service Subcategory value MUST have one and only one Service Category parent. -* Though a given *service* can have multiple purposes, each *service* SHOULD have one and only one Subcategory that best aligns with its primary purpose. +The ServiceSubcategory column adheres to the following requirements: + +* ServiceSubcategory is RECOMMENDED to be present in a FOCUS dataset and MUST NOT be null. +* ServiceSubcategory is of type String and MUST be one of the allowed values. +* Each ServiceSubcategory value MUST have one and only one parent ServiceCategory as specified in the allowed values below. +* Though a given *service* can have multiple purposes, each *service* SHOULD have one and only one ServiceSubcategory that best aligns with its primary purpose. ## Column ID @@ -24,7 +26,7 @@ Secondary classification of the Service Category for a *service* based on its co | Constraint | Value | | :-------------- | :------------- | | Column type | Dimension | -| Feature level | Optional | +| Feature level | Recommended | | Allows nulls | False | | Data type | String | | Value format | Allowed Values | From 77496775c5e1033b34fc6c7fdb4ef8c6252adac9 Mon Sep 17 00:00:00 2001 From: Christopher Harris Date: Thu, 3 Oct 2024 19:58:24 -0400 Subject: [PATCH 40/52] [EDITORIAL - Alternate version] Mark commitment discount purchase's pricing_category as "Standard" (#579) Co-authored-by: AWS-ZachErdman --- specification/appendix/commitment_discounts.md | 10 +++++----- specification/columns/pricingcategory.md | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/specification/appendix/commitment_discounts.md b/specification/appendix/commitment_discounts.md index 6f83a618f..ed4733c68 100644 --- a/specification/appendix/commitment_discounts.md +++ b/specification/appendix/commitment_discounts.md @@ -31,7 +31,7 @@ Within the FOCUS specification, the following examples demonstrate how a *commit ### Purchase *Rows* -All *commitment discount* purchases appear with a positive `BilledCost`, `PricingCategory` as "Committed", and with the *commitment discount's* id populating both the `ResourceId` and `CommitmentDiscountId` value. One-time purchases appear as a single record with `ChargeCategory` as "Purchase", `ChargeFrequency` as "One-Time", and the total quantity and units for *commitment discount's* *term* reflected as `CommitmentDiscountQuantity` and `CommitmentDiscountUnit`, respectively. +All *commitment discount* purchases appear with a positive `BilledCost`, `PricingCategory` as "Standard", and with the *commitment discount's* id populating both the `ResourceId` and `CommitmentDiscountId` value. One-time purchases appear as a single record with `ChargeCategory` as "Purchase", `ChargeFrequency` as "One-Time", and the total quantity and units for *commitment discount's* *term* reflected as `CommitmentDiscountQuantity` and `CommitmentDiscountUnit`, respectively. Recurring purchases are allocated across all corresponding *charge periods* of the *term* when `ChargeCategory` is "Purchase", `ChargeFrequency` is "Recurring", and `CommitmentDiscountQuantity` and `CommitmentDiscountUnit` are reflected only for that *charge period*. @@ -50,7 +50,7 @@ The entire *commitment discount* is billed _once_ during the first *charge perio "ChargePeriodEndDate": "2024-01-01T00:00:00Z", "ChargeCategory": "Purchase", "ChargeFrequency": "One-Time", - "PricingCategory": "Committed", + "PricingCategory": "Standard", "ResourceId": "", "BilledCost": 8760.00, "EffectiveCost": 0.00, @@ -74,7 +74,7 @@ The *commitment discount* is billed across all 8,760 (`24 hours * 365 days`) *ch "ChargePeriodEndDate": "2023-01-01T01:00:00Z", "ChargeCategory": "Purchase", "ChargeFrequency": "Recurring", - "PricingCategory": "Committed", + "PricingCategory": "Standard", "ResourceId": "", "BilledCost": 1.00, "EffectiveCost": 0.00, @@ -100,7 +100,7 @@ With a 50/50 split, half of the commitment is billed _once_ during the first *ch "ChargePeriodEndDate": "2024-01-01T00:00:00Z", "ChargeCategory": "Purchase", "ChargeFrequency": "One-Time", - "PricingCategory": "Committed", + "PricingCategory": "Standard", "ResourceId": "", "BilledCost": 4380.00, "EffectiveCost": 0.00, @@ -115,7 +115,7 @@ With a 50/50 split, half of the commitment is billed _once_ during the first *ch "ChargePeriodEndDate": "2023-01-01T01:00:00Z", "ChargeCategory": "Purchase", "ChargeFrequency": "Recurring", - "PricingCategory": "Committed", + "PricingCategory": "Standard", "ResourceId": "", "BilledCost": 0.50, "EffectiveCost": 0.00, diff --git a/specification/columns/pricingcategory.md b/specification/columns/pricingcategory.md index 1636622d9..ae0369498 100644 --- a/specification/columns/pricingcategory.md +++ b/specification/columns/pricingcategory.md @@ -38,9 +38,9 @@ Allowed values: | Value | Description | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Standard | Charges priced at the agreed upon rate for the billing account, including [*negotiated discounts*](#glossary:negotiated-discount). This includes any flat rate and volume/tiered pricing but does not include dynamic or *commitment discount* pricing. | +| Standard | Charges priced at the agreed upon rate for the billing account, including [*negotiated discounts*](#glossary:negotiated-discount). This pricing includes any flat rate and volume/tiered pricing but does not include dynamic pricing or reduced pricing due to the application of a *commitment discount*. This does include the purchase of a commitment discount at agreed upon rates. | | Dynamic | Charges priced at a variable rate determined by the provider. This includes any product or service with a unit price the provider can change without notice, like interruptible or low priority resources. | -| Committed | Charges with reduced prices due to a *commitment discount* specified by the Commitment Discount ID. | +| Committed | Charges with reduced pricing due to the application of the *commitment discount* specified by the Commitment Discount ID. | | Other | Charges priced in a way not covered by another pricing category. | ## Introduced (version) From 412eb24f02a85745b214e1ba4664c8b87bf5354e Mon Sep 17 00:00:00 2001 From: Christopher Harris Date: Thu, 3 Oct 2024 20:15:28 -0400 Subject: [PATCH 41/52] Adding 'Commitment Discount Visibility' to v1.1 Release Planning (#577) `Commitment Discount Visibility` --> Provide deeper visibility into how various commitment discount purchases are amortized across eligible resources. --- RELEASE-PLANNING.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RELEASE-PLANNING.md b/RELEASE-PLANNING.md index 34b21361f..2063999ad 100644 --- a/RELEASE-PLANNING.md +++ b/RELEASE-PLANNING.md @@ -22,6 +22,10 @@ This section outlines the planned release schedule and key milestones for the FO
  • Move beyond the highest-level service categorization to a sub-categorization for services while adding flexibility for providers to share their native categorizations within FOCUS.
  • + Commitment Discount Visibility +
      +
    • Provide deeper visibility into how various commitment discount purchases are amortized across eligible resources.
    • +
    Capacity Reservation
    • Ability to represent on-demand capacity reservations within FOCUS datasets. From e34a65e9b8169ed629ae74d5c7b5e0f5b106dae2 Mon Sep 17 00:00:00 2001 From: Christopher Harris Date: Thu, 3 Oct 2024 20:31:16 -0400 Subject: [PATCH 42/52] Commitment Discount {Quantity,Unit} - Consistency review edits (#550) Adds correction-based logic and reduces duplication of clauses --------- Co-authored-by: Irena Jurica --- .../columns/commitmentdiscountquantity.md | 14 +++++++------- specification/columns/commitmentdiscountunit.md | 3 ++- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/specification/columns/commitmentdiscountquantity.md b/specification/columns/commitmentdiscountquantity.md index 79b096479..892b103f5 100644 --- a/specification/columns/commitmentdiscountquantity.md +++ b/specification/columns/commitmentdiscountquantity.md @@ -10,19 +10,19 @@ The CommitmentDiscountQuantity column adheres to the following requirements: * CommitmentDiscountQuantity MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. * CommitmentDiscountQuantity MUST be of type Decimal and MUST conform to [Numeric Format](#numericformat) requirements. -* CommitmentDiscountQuantity MAY be negative if [*ChargeClass*](#chargeclass) is "Correction". +* CommitmentDiscountQuantity MAY be null or any valid decimal value if [*CommitmentDiscountId*](#commitmentdiscountid) is not null and [*ChargeClass*](#chargeclass) is "Correction". -In cases where the *ChargeCategory* is "Purchase" and [*CommitmentDiscountId*](#commitmentdiscountid) is not null, the following applies: +In cases where the *ChargeCategory* is "Purchase", *CommitmentDiscountId* is not null, and *ChargeClass* is not "Correction", the following applies: * When [*ChargeFrequency*](#chargefrequency) is "One-Time", and *CommitmentDiscountId* is not null, CommitmentDiscountQuantity MUST be the positive quantity of *CommitmentDiscountUnits*, paid fully or partially upfront, that is eligible for consumption over the *commitment discount's* *term*. * When *ChargeFrequency* is "Recurring", and *CommitmentDiscountId* is not null, CommitmentDiscountQuantity MUST be the positive quantity of *CommitmentDiscountUnits* that is eligible for consumption for each *charge period* that corresponds with the purchase. -In cases where the *ChargeCategory* is "Usage" and *CommitmentDiscountId* is not null, the following applies: +In cases where the *ChargeCategory* is "Usage", *CommitmentDiscountId* is not null, and *ChargeClass* is not "Correction", the following applies: -* When *CommitmentDiscountStatus* is "Used", and *ChargeClass* is not "Correction", CommitmentDiscountQuantity MUST be the positive, metered quantity of *CommitmentDiscountUnits* that is consumed over the *row's* *charge period*. -* When *CommitmentDiscountStatus* is "Unused", and *ChargeClass* is not "Correction", CommitmentDiscountQuantity MUST be the remaining, positive, unused quantity of *CommitmentDiscountUnits* for the *row's* *charge period*. +* When *CommitmentDiscountStatus* is "Used", CommitmentDiscountQuantity MUST be the positive, metered quantity of *CommitmentDiscountUnits* that is consumed over the *row's* *charge period*. +* When *CommitmentDiscountStatus* is "Unused", CommitmentDiscountQuantity MUST be the remaining, positive, unused quantity of *CommitmentDiscountUnits* for the *row's* *charge period*. -CommitmentDiscountQuantity MUST be null for all other *ChargeCategory* values. +CommitmentDiscountQuantity MUST be null in all other cases. ## Column ID @@ -40,7 +40,7 @@ The amount of a *commitment discount* purchased or accounted for in *commitment | Constraint | Value | |:----------------|:-----------------| -| Column type | Dimension | +| Column type | Metric | | Feature level | Conditional | | Allows nulls | True | | Data type | Decimal | diff --git a/specification/columns/commitmentdiscountunit.md b/specification/columns/commitmentdiscountunit.md index 39c8784db..fc91838b1 100644 --- a/specification/columns/commitmentdiscountunit.md +++ b/specification/columns/commitmentdiscountunit.md @@ -7,7 +7,8 @@ The CommitmentDiscountUnit column adheres to the following requirements: * CommitmentDiscountUnit MUST be present in a FOCUS dataset when the provider supports [*commitment discounts*](#glossary:commitment-discount). * CommitmentDiscountUnit MUST be of type String, and the units of measure used in CommitmentDiscountUnit SHOULD adhere to the values and format requirements specified in the [UnitFormat](#unitformat) attribute. * The CommitmentDiscountUnit MUST be the same across all *rows* where *CommitmentDiscountQuantity* has the same [*CommitmentDiscountId*](#commitmentdiscountid). -* CommitmentDiscountUnit MUST NOT be null when *CommitmentDiscountId* is not null. +* CommitmentDiscountUnit MAY be null if [*CommitmentDiscountId*](#commitmentdiscountid) is not null and [*ChargeClass*](#chargeclass) is "Correction". +* CommitmentDiscountUnit MUST NOT be null when *CommitmentDiscountId* is not null and *ChargeClass* is not "Correction". * CommitmentDiscountUnit MUST be null in all other cases. In cases where the CommitmentDiscountUnit is not null, the following applies: From 02a8df5802719c866814edd7e5a415bfc66705ff Mon Sep 17 00:00:00 2001 From: Joaquin Date: Thu, 3 Oct 2024 17:47:27 -0700 Subject: [PATCH 43/52] [EDITORIAL] Update the list of FOCUS release v1.1 contributors (#583) This pull request provides a draft list of FOCUS members who contributed to the FOCUS Release v1.1 specifications through various means, including submitting pull requests, reviewing existing submissions, or actively participating in discussions. --------- Co-authored-by: Karl <133434112+kk09v@users.noreply.github.com> Co-authored-by: Udam Dewaraja --- specification/contributors.md | 61 ++++++----------------------------- 1 file changed, 10 insertions(+), 51 deletions(-) diff --git a/specification/contributors.md b/specification/contributors.md index 2674fe1e6..8ecc94997 100644 --- a/specification/contributors.md +++ b/specification/contributors.md @@ -2,80 +2,39 @@ ### Maintainers -Thanks to the following FOCUS Maintainers for their leadership and contributions to the FOCUS specification. +Thanks to the following FOCUS Maintainers for their leadership and contributions to the FOCUS Release **v1.1** specification. +* Alex Hullah (Goldman Sachs) * Christopher Harris (Datadog) -* Dennis Park-Rodriguez (Amazon Web Services) -* Erik Peterson (CloudZero) * Irena Jurica (Neos) * Joaquin Prado (FinOps Foundation) * Karl Kraft (Walmart) * Larry Advey (Twilio) * Michael Flanakin (Microsoft) -* Mike Fuller (FinOps Foundation) * Riley Jenkins (Domo) -* Rupa Patel (Google) +* Shawn Alpay (Envisor / FinOps Foundation) * Udam Dewaraja (FinOps Foundation) +* Zach Erdman (Amazon Web Services) ### Contributors -Thanks to the following FOCUS members for their contributions to the FOCUS specification. +Thanks to the following FOCUS members for their contributions to the FOCUS Release **v1.1** specification. * Adam Schwartz (Ernst & Young) -* Alex Hullah (Goldman Sachs) -* Amit Wadhwa (Google) -* Anand Tripathi (Amazon Web Services) -* Anderson Oliveira (Farfetch.com) * Andrew Qu (Everest) -* Anne Johnston (Capital One) * Arun Ramakrishnan (Oracle) -* Ben Shy (Microsoft) -* Ben Swoboda (NetApp) -* Ben Zhou (Apptio) -* Casey Doran (Apptio) -* Chandra Devarajan (CloudTrakr) -* Chew Esmero (Alphaus Inc.) -* Colin Jack (Snow Software) -* Deeja Cruz (Datadog) -* Eleni Rundle (Google) +* Erik Peterson (CloudZero) * George Parker (Salesforce) * Graham Murphy (Australian Retirement Trust) -* Harish Kumar Munagapat (Kyndryl) -* Hrishikesh Sardar (Kyndryl) -* Ilia Semenov (CloudThread) -* Jacky Liu (Google Cloud) -* Jacqui Wilson (Old Mutual South Africa) * Janine Pickard-Green (MagicOrange Group Limited) -* Jason Kelly (Anglepoint Group Inc) -* Joe Ferrero (DB Gurus Inc) * John Grubb (Platform.sh) -* Joshua Kwan (Ternary) -* Letian Wang (Atlassian) -* Luna Bernal (Twilio) +* Joseph John (Microsoft) * Marc Perreaut (Amadeus) -* Marcin Walkow (Nordcloud) -* Mark Krawczeniuk (NetApp) -* Matt Ray (Kubecost) -* Michael Arkoosh (Vega) -* Mike Polson (VMWare) -* Nick Kotze (Surveil) -* Nicolas Fonrose (Teevity) -* Peter Marton (OpenMeter.io) -* Ray Ding (Accenture) -* Ricardo Triana (Accenture) -* Rodney Joyce (CloudMonitor) +* Rob Martin (FinOps Foundation) +* Rupa Patel (Google) * Sanjna Srivatsa (VMWare) -* Shawn Alpay (Envisor) -* Sireesha Oram (Kyndryl) * Sonal Garg (Kyndryl) -* Sumaira Nazir (Platform.sh) -* Tatiana Dubovchenko (Flexera) -* Tim O'Brien (Walmart) -* Trey Morgan (Microsoft) -* Trig Ghosh (Accenture) -* Webb Brown (Kubecost) -* Yuriy Prykhodko (Amazon Web Services) -* Zach Erdman (Amazon Web Services) +* Tim Wright (Google) ## Steering Committee Members From 44b86108da706b200de81e72d88a714b7985ef51 Mon Sep 17 00:00:00 2001 From: Udam Dewaraja Date: Fri, 4 Oct 2024 12:02:57 -0700 Subject: [PATCH 44/52] FOCUS-580: remove use case library and link to the FOCUS website (#581) --- specification/use_case_library.md | 45 +------------------------------ 1 file changed, 1 insertion(+), 44 deletions(-) diff --git a/specification/use_case_library.md b/specification/use_case_library.md index b8b5da96c..23069b781 100644 --- a/specification/use_case_library.md +++ b/specification/use_case_library.md @@ -1,46 +1,3 @@ # Use Case Library -The following table contains a set of commonly performed FinOps scenarios that were used as a basis for developing this specification. These use cases were developed by FinOps practitioners. - -| Persona | Capability | Use Case | FOCUS Columns | -|:--|:--|:--|:--| -| Business / Product Owner | Budget Management | As a Business/Product Owner, I need to compare actual usage costs incurred within a time period to the amount forecasted. | BilledCost
      BillingAccountId
      BillingAccountName
      ChargePeriodStart
      ChargePeriodEnd
      ChargeCategory
      Provider | -| Engineering & Operations | Budget Management | As an Engineering Manager who wants to reduce their billed cost for Compute for a specific provider, I want to understand what is my current rate of commitment discount (without negotiated discounts) per type of commitment, so that I can strategize further purchases | BillingPeriodStart
      CommitmentDiscountType
      EffectiveCost
      ProviderName
      ServiceName
      SubAccountId
      SubAccountName | -| Engineering & Operations | Data Analysis and Showback | As an Engineer, I want to understand the costs of the components that belong to an application | ChargeDescription
      ChargePeriodStart
      EffectiveCost
      ResourceId
      ResourceName
      ResourceType
      ServiceCategory
      ServiceName
      SkuId
      Tags | -| Engineering & Operations | Data Analysis and Showback | As an Engineer, I want to understand the costs of the components for a specific resource | ChargePeriodStart
      EffectiveCost
      ResourceId
      ResourceName
      SkuId | -| Engineering & Operations | Data Analysis and Showback | As an Engineer, I want to understand the costs of all components and resources within a subaccount | ChargePeriodStart
      EffectiveCost
      ResourceId
      ResourceName
      SkuId
      SubAccountId | -| Engineering & Operations | Data Analysis and Showback | As an Engineering & Operations person I would like to analyze the usage of serverless requests on a weekly basis to identity potential optimization candidates | BilledCost
      ProviderName
      ChargePeriodStart
      ChargePeriodEnd
      SkuId
      ConsumedQuantity
      Tags
      ConsumedUnit | -| Engineering & Operations | Data Analysis and Showback | As an Engineer, I need to extract a ranked list of the top 10 service cost drivers within a sub account from a time period | ChargePeriodStart
      EffectiveCost
      SubAccountId
      SubAccountName
      ServiceName | -| Engineering & Operations | Workload Management & Automation | As an Engineer I need to ensure my costs within a region are distributed across the different availability zones in an expected manner. | ProviderName
      AvailabilityZone
      RegionId
      RegionName
      BillingPeriodStart
      EffectiveCost | -| Engineering & Operations | Workload Management & Automation | As an Engineering manager, I need to see the cost of each compute resource in a production SubAccount I'm responsible for. | ResourceId
      ResourceName
      ChargePeriodStart
      ChargePeriodEnd
      ServiceName
      ServiceCategory
      PricingQuantity
      EffectiveCost | -| Finance | Budget Management | As a person in Finance, I need to update cloud budget with actual cost details within a billing period | BilledCost
      BillingPeriodStart
      BillingPeriodEnd
      ProviderName | -| Finance | Budget Management | As a person in Finance, I need to update budget, by application, with actual cost details within a billed time period | BilledCost
      BillingPeriodStart
      BillingPeriodEnd
      ProviderName
      Tags | -| Finance | Budget Management | As a person in Finance, I need to track tax costs month over month. | BillingPeriodStart
      BilledCost
      ChargeCategory
      ProviderName | -| Finance | Budget Management | As a Financial Analyst or member of the company's treasury, I would like to understand what volume of commitment discount charges are going to reoccur in the coming financial year | ChargeFrequency
      BillingPeriodStart
      BilledCost | -| Finance | Data Analysis and Showback | As a Finance person of a company that sells SaaS services, I need to determine the resource quantity and type used by a customer so that a monthly invoice can be issued to the customer. | ProviderName
      BillingPeriodStart
      SkuId
      PricingQuantity
      ConsumedQuantity
      ConsumedUnit
      Tags | -| Finance | Data Analysis and Showback | As a person in Finance, I need a report of all cost associated with a product from all geographic locations for a given month. | BilledCost
      BillingCurrency
      BillingAccountId
      BillingAccountName
      BillingPeriodEnd
      ProviderName
      Tags | -| Finance | FinOps & Intersecting Frameworks | As a person in Finance, I need a report of service-level cost within a specific Sub Account as a part of a private pricing negotiation. | BillingPeriodStart
      EffectiveCost
      ProviderName
      ServiceName
      SubAccountId
      SubAccountName | -| Finance | Forecasting | As a person in Finance, I need to forecast amortized costs on a month over month basis, based on historical trends | BillingPeriodStart
      ChargeCategory
      EffectiveCost
      PricingUnit
      ProviderName
      ServiceName
      ServiceCategory | -| Finance | Forecasting | As a person in Finance, I need to forecast cashflow on a month over month basis, based on historical trends | BillingPeriodStart
      ChargeCategory
      ChargeDescription
      BilledCost
      BillingCurrency
      ProviderName
      ServiceName
      ServiceCategory | -| FinOps Practitioner | Data Analysis and Showback | As a FinOps practitioner, I need to analyze service costs month over month, over a time period | EffectiveCost
      BillingPeriodStart
      ProviderName
      ServiceName | -| FinOps Practitioner | Data Analysis and Showback | As a FinOps practitioner, I need to analyze service costs, by region, over a time period | EffectiveCost
      BillingPeriodStart
      ProviderName
      RegionId
      RegionName
      ServiceName | -| FinOps Practitioner | Data Analysis and Showback | As a FinOps practitioner, I need to analyze Compute Engine service costs month over month for a period of time to identify accounts spending the most money on Compute Engine | BilledCost
      BillingPeriodStart
      ProviderName
      ResourceId
      ResourceName
      ServiceName
      SubAccountId
      SubAccountName | -| FinOps Practitioner | Data Analysis and Showback | As a FinOps practitioner, I want to monitor how much we are spending on a specific SaaS product purchased via the cloud service provider's marketplace. | ChargePeriodStart
      ChargePeriodEnd
      EffectiveCost
      InvoiceIssuer
      ProviderName
      Publisher | -| FinOps Practitioner | Data Analysis and Showback | As a FinOps Practitioner, I need to understand what we are spending across providers, billing periods, and service categories | ProviderName
      BillingPeriodStart
      BilledCost
      BillingCurrency
      ServiceCategory | -| FinOps Practitioner | FinOps & Intersecting Frameworks | As a FinOps Practitioner, I need to verify the accuracy of the cloud service provider invoices | ProviderName
      BillingAccountId
      BillingAccountName
      BillingPeriodStart
      BilledCost
      BillingCurrency | -| FinOps Practitioner | FinOps & Intersecting Frameworks | As a FinOps Practitioner, I need to verify the accuracy of the cloud service provider invoices and the underlying services | ProviderName
      BillingAccountId
      BillingAccountName
      BillingPeriodStart
      BilledCost
      BillingCurrency
      ServiceName | -| FinOps Practitioner | FinOps & Intersecting Frameworks | As a FinOps Practitioner, I need to reconcile discounts on the cloud service provider invoices and the underlying services | ProviderName
      BillingAccountId
      BillingAccountName
      BillingPeriodStart
      BilledCost
      BillingCurrency
      EffectiveCost
      ListCost
      ServiceName | -| FinOps Practitioner | FinOps & Intersecting Frameworks | As a FinOps Practitioner, I need to analyze usage data of resources | ChargePeriodStart
      ChargeCategory
      EffectiveCost
      ProviderName
      PricingQuantity
      ConsumedQuantity
      ResourceId
      ServiceName
      SkuId
      ConsumedUnit | -| FinOps Practitioner | Forecasting | As a FinOps Practitioner, I need to forecast costs, based on historical usage trends and rates | BillingPeriodStart
      ChargeCategory
      ChargeDescription
      EffectiveCost
      ProviderName
      PricingQuantity
      ConsumedQuantity
      RegionId
      ServiceCategory
      ServiceName
      SkuId
      ConsumedUnit | -| FinOps Practitioner | Managing Anomalies | As a FinOps Practitioner, I need to see the daily costs across all cloud providers, billing accounts, and sub accounts | BillingAccountId
      SubAccountId
      ChargePeriodStart
      ChargePeriodEnd
      ProviderName
      EffectiveCost | -| FinOps Practitioner | Managing Anomalies | As a FinOps Practitioner, I need to see the daily costs across all cloud providers, billing accounts, sub accounts, and region | BillingAccountId
      SubAccountId
      ChargePeriodStart
      ChargePeriodEnd
      EffectiveCost
      ProviderName
      RegionId
      RegionName | -| FinOps Practitioner | Managing Anomalies | As a FinOps practitioner, I need to see the daily costs across all cloud providers, billing accounts, sub accounts, and service | BillingAccountId
      SubAccountId
      ChargePeriodStart
      ChargePeriodEnd
      EffectiveCost
      ProviderName
      ServiceName | -| FinOps Practitioner | Managing Commitment Discounts | As a FinOps Practitioner, I want to track all commitment discounts purchased for a time period | ProviderName
      BillingAccountId
      CommitmentDiscountId
      CommitmentDiscountType
      BilledCost
      ChargePeriodStart
      ChargeCategory | -| FinOps Practitioner | Managing Commitment Discounts | As a FinOps Practitioner, I want to track unused commitment charges in any given time period so that I consider them in my future commitment planning or remedy them | CommitmentDiscountStatus (filter)
      CommitmentDiscountId
      BilledCost
      ChargePeriodStart | -| FinOps Practitioner | Resource Utilization & Efficiency | As a FinOps Practitioner, I need to analyze the fleet diversity in order to run a campaign to standardize application architecture. | ChargeCategory
      ChargeDescription
      ChargePeriodStart
      ProviderName
      ResourceType
      SubAccountId
      ServiceName | -| FinOps Practitioner | Resource Utilization & Efficiency | As a FinOps Practitioner, I need to analyze the fleet diversity in order to run a campaign to standardize application architecture within a specific service | ChargeCategory
      ChargeDescription
      ChargePeriodStart
      ProviderName
      ResourceType
      SubAccountId
      ServiceName | -| FinOps Practitioner | Resource Utilization & Efficiency | As a FinOps Practitioner, I need to identify total refunds within a billing period. | ProviderName
      BillingAccountId
      ServiceCategory
      BilledCost
      BillingPeriodStart
      ChargeCategory
      ChargeClass | -| FinOps Practitioner | Resource Utilization & Efficiency | As a FinOps Practitioner, I need to identify refunds across sub accounts within a billing period. | ProviderName
      BillingAccountId
      ServiceCategory
      BilledCost
      BillingPeriodStart
      ChargeCategory
      ChargeClass
      SubAccountId | -| FinOps Practitioner | Workload Management & Automation | As a FinOps Practitioner, I need to do an analysis on compliance to data residency requirements across all regions | ChargePeriodStart
      ProviderName
      RegionId
      RegionName
      SubAccountId | -| Procurement | Data Analysis and Showback | As a person in Procurement, I need to understand what we are spending, across billing periods, across service categories to focus negotiations toward highest costing items | ProviderName
      BillingAccountId
      BillingAccountName
      BillingCurrency
      BilledCost
      BillingPeriodStart
      ServiceCategory
      ServiceName | -| Procurement, Finance, FinOps Practitioner | FinOps & Intersecting Frameworks | Multiple personas in an organization need to know the top SKU Codes based on spend, so that they can achieve multiple goals such as contract negotiation, SKU based forecasting, or high unit cost cleanup activities. | ChargePeriodStart
      ChargePeriodEnd
      ListCost
      PricingUnit
      ListUnitPrice
      PricingQuantity
      SkuId
      SkuPriceId
      ProviderName | +This specification is based on a set of common FinOps use cases, which are publicly available at [https://focus.finops.org/use-cases/](https://focus.finops.org/use-cases/). Developed by FinOps practitioners, these use cases are organized by persona and capability, making it easy to find relevant scenarios. Each use case includes sample SQL queries to help you get started with implementation. From 32d8e83b6856dd47664976a556b79adb5e86be30 Mon Sep 17 00:00:00 2001 From: Alex Hullah Date: Sat, 5 Oct 2024 00:17:36 +0100 Subject: [PATCH 45/52] Adding Usability Constraints for Aggregation (#559) Adding Usability Constraints for Aggregation, to support commitment utilization calculation --------- Co-authored-by: Irena Jurica Co-authored-by: Christopher Harris Co-authored-by: Joaquin --- specification/columns/commitmentdiscountquantity.md | 6 ++++-- specification/columns/contractedcost.md | 6 ++++-- specification/columns/contractedunitprice.md | 4 ++++ specification/columns/listcost.md | 6 ++++-- specification/columns/listunitprice.md | 4 ++++ specification/columns/pricingquantity.md | 6 +++++- 6 files changed, 25 insertions(+), 7 deletions(-) diff --git a/specification/columns/commitmentdiscountquantity.md b/specification/columns/commitmentdiscountquantity.md index 892b103f5..b78b40965 100644 --- a/specification/columns/commitmentdiscountquantity.md +++ b/specification/columns/commitmentdiscountquantity.md @@ -4,8 +4,6 @@ Commitment Discount Quantity is the amount of a [*commitment discount*](#commitm When *CommitmentDiscountCategory* is "Usage" (usage-based *commitment discounts*), the Commitment Discount Quantity reflects the predefined amount of usage purchased or consumed. If [*commitment discount flexibility*](glossary:commitment-discount-flexibility) is applicable, this value may be further transformed based on additional, provider-specific requirements. When *CommitmentDiscountCategory* is "Spend" (spend-based *commitment discounts*), the Commitment Discount Quantity reflects the predefined amount of spend purchased or consumed. -**Important:** When aggregating Commitment Discount Quantity for utilization calculations, it's important to exclude *commitment discount* purchases (i.e. when *ChargeCategory* is "Purchase") that are paid to cover future eligible charges (e.g., *Commitment Discount*). This exclusion helps prevent double counting of these quantities in the aggregation. - The CommitmentDiscountQuantity column adheres to the following requirements: * CommitmentDiscountQuantity MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. @@ -36,6 +34,10 @@ Commitment Discount Quantity The amount of a *commitment discount* purchased or accounted for in *commitment discount* related *rows* that is denominated in *Commitment Discount Units*. +## Usability Constraints + +**Aggregation:** When aggregating Commitment Discount Quantity for commitment utilization calculations, it's important to exclude *commitment discount* purchases (i.e. when *ChargeCategory* is "Purchase") that are paid to cover future eligible charges (e.g., *Commitment Discount*). Otherwise, when accounting for all upfront or accrued purchases, it's important to exclude *commitment discount* usage (i.e. when *ChargeCategory* is "Usage"). This exclusion helps prevent double counting of these quantities in the aggregation. + ## Content constraints | Constraint | Value | diff --git a/specification/columns/contractedcost.md b/specification/columns/contractedcost.md index e44233c8e..2c15aac25 100644 --- a/specification/columns/contractedcost.md +++ b/specification/columns/contractedcost.md @@ -2,8 +2,6 @@ Contracted Cost represents the cost calculated by multiplying [*contracted unit price*](#glossary:contracted-unit-price) and the corresponding [Pricing Quantity](#pricingquantity). Contracted Cost is denominated in the [Billing Currency](#billingcurrency) and is commonly used for calculating savings based on negotiation activities, by comparing it with [List Cost](#listcost). If [*negotiated discounts*](#glossary:negotiated-discount) are not applicable, the Contracted Cost defaults to the List Cost. -**Important:** When aggregating Contracted Cost for savings calculations, it's important to exclude either one-time or recurring charges ([Charge Category](#chargecategory) "Purchase") that are paid to cover future eligible charges (e.g., [Commitment Discount](#glossary:commitment-discount)) or the covered charges themselves. This exclusion helps prevent double counting of these charges in the aggregation. Which set of charges to exclude depends on whether cost are aggregated on a billed basis (exclude covered charges) or accrual basis (exclude Purchases for future charges). For instance, charges categorized as [Charge Category](#chargecategory) "Purchase" and their related [Charge Category](#chargecategory) "Tax" charges for a Commitment Discount might be excluded from an accrual basis cost aggregation of Contracted Cost. This is because the "Usage" and "Tax" charge records provided during the term of the commitment discount already specify the Contracted Cost. Purchase charges that cover future eligible charges can be identified by filtering for [Charge Category](#chargecategory) "Purchase" records with a [Billed Cost](#billedcost) greater than 0 and an [Effective Cost](#effectivecost) equal to 0. - The ContractedCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. When [ContractedUnitPrice](#contractedunitprice) is present and not null, multiplying the ContractedUnitPrice by PricingQuantity MUST produce the ContractedCost, except in cases of [ChargeClass](#chargeclass) "Correction", which may address PricingQuantity or any cost discrepancies independently. In cases where the ContractedUnitPrice is present and null, the following applies: @@ -23,6 +21,10 @@ Contracted Cost Cost calculated by multiplying *contracted unit price* and the corresponding Pricing Quantity. +## Usability Constraints + +**Aggregation:** When aggregating Contracted Cost for savings calculations, it's important to exclude either [Charge Category](#chargecategory) "Purchase" charges (one-time and recurring) that are paid to cover future eligible charges (e.g., [Commitment Discount](#glossary:commitment-discount)) or the covered [Charge Category](#chargecategory) "Usage" charges themselves. This exclusion helps prevent double counting of these charges in the aggregation. Which set of charges to exclude depends on whether cost are aggregated on a billed basis (exclude covered charges) or accrual basis (exclude Purchases for future charges). For instance, charges categorized as [Charge Category](#chargecategory) "Purchase" and their related [Charge Category](#chargecategory) "Tax" charges for a Commitment Discount might be excluded from an accrual basis cost aggregation of Contracted Cost. This is because the "Usage" and "Tax" charge records provided during the term of the commitment discount already specify the Contracted Cost. Purchase charges that cover future eligible charges can be identified by filtering for [Charge Category](#chargecategory) "Purchase" records with a [Billed Cost](#billedcost) greater than 0 and an [Effective Cost](#effectivecost) equal to 0. + ## Content Constraints | Constraint | Value | diff --git a/specification/columns/contractedunitprice.md b/specification/columns/contractedunitprice.md index 4061d0ec3..d0deec909 100644 --- a/specification/columns/contractedunitprice.md +++ b/specification/columns/contractedunitprice.md @@ -16,6 +16,10 @@ Contracted Unit Price The agreed-upon unit price for a single Pricing Unit of the associated SKU, inclusive of negotiated discounts, if present, while excluding negotiated commitment discounts or any other discounts. +## Usability Constraints + +**Aggregation:** Column values should only be viewed in the context of their row and not aggregated to produce a total. + ## Content Constraints | Constraint | Value | diff --git a/specification/columns/listcost.md b/specification/columns/listcost.md index de5fabc87..cb0e69877 100644 --- a/specification/columns/listcost.md +++ b/specification/columns/listcost.md @@ -2,8 +2,6 @@ List Cost represents the cost calculated by multiplying the [*list unit price*](#glossary:list-unit-price) and the corresponding [Pricing Quantity](#pricingquantity). List Cost is denominated in the [Billing Currency](#billingcurrency) and is commonly used for calculating savings based on various rate optimization activities, by comparing it with [Contracted Cost](#contractedcost), [Billed Cost](#billedcost) and [Effective Cost](#effectivecost). -**Important:** When aggregating List Cost for savings calculations, it's important to exclude either one-time or recurring charges ([Charge Category](#chargecategory) "Purchase") that are paid to cover future eligible charges (e.g., [Commitment Discount](#glossary:commitment-discount)) or the covered charges themselves. This exclusion helps prevent double counting of these charges in the aggregation. Which set of charges to exclude depends on whether cost are aggregated on a billed basis (exclude covered charges) or accrual basis (exclude Purchases for future charges). For instance, charges categorized as [Charge Category](#chargecategory) "Purchase" and their related [Charge Category](#chargecategory) "Tax" charges for a Commitment Discount might be excluded from an accrual basis cost aggregation of List Cost. This is because the "Usage" and "Tax" charge records provided during the term of the commitment discount already specify the List Cost. Purchase charges that cover future eligible charges can be identified by filtering for [Charge Category](#chargecategory) "Purchase" records with a [Billed Cost](#billedcost) greater than 0 and an [Effective Cost](#effectivecost) equal to 0. - The ListCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. When [ListUnitPrice](#listunitprice) is present and not null, multiplying the ListUnitPrice by PricingQuantity MUST produce the ListCost, except in cases of [ChargeClass](#chargeclass) "Correction", which may address PricingQuantity or any cost discrepancies independently. In cases where the ListUnitPrice is present and is null, the following applies: @@ -23,6 +21,10 @@ List Cost Cost calculated by multiplying List Unit Price and the corresponding Pricing Quantity. +## Usability Constraints + +**Aggregation:** When aggregating List Cost for savings calculations, it's important to exclude either [Charge Category](#chargecategory) "Purchase" charges (one-time and recurring) that are paid to cover future eligible charges (e.g., [Commitment Discount](#glossary:commitment-discount)) or the covered [Charge Category](#chargecategory) "Usage" charges themselves. This exclusion helps prevent double counting of these charges in the aggregation. Which set of charges to exclude depends on whether cost are aggregated on a billed basis (exclude covered charges) or accrual basis (exclude Purchases for future charges). For instance, charges categorized as [Charge Category](#chargecategory) "Purchase" and their related [Charge Category](#chargecategory) "Tax" charges for a Commitment Discount might be excluded from an accrual basis cost aggregation of List Cost. This is because the "Usage" and "Tax" charge records provided during the term of the commitment discount already specify the List Cost. Purchase charges that cover future eligible charges can be identified by filtering for [Charge Category](#chargecategory) "Purchase" records with a [Billed Cost](#billedcost) greater than 0 and an [Effective Cost](#effectivecost) equal to 0. + ## Content Constraints | Constraint | Value | diff --git a/specification/columns/listunitprice.md b/specification/columns/listunitprice.md index 531bd716c..c014b2382 100644 --- a/specification/columns/listunitprice.md +++ b/specification/columns/listunitprice.md @@ -16,6 +16,10 @@ List Unit Price The suggested provider-published unit price for a single Pricing Unit of the associated SKU, exclusive of any discounts. +## Usability Constraints + +**Aggregation:** Column values should only be viewed in the context of their row and not aggregated to produce a total. + ## Content Constraints | Constraint | Value | diff --git a/specification/columns/pricingquantity.md b/specification/columns/pricingquantity.md index b811cd71b..b858443da 100644 --- a/specification/columns/pricingquantity.md +++ b/specification/columns/pricingquantity.md @@ -16,7 +16,11 @@ Pricing Quantity The volume of a given SKU associated with a *resource* or *service* used or purchased, based on the Pricing Unit. -## Content constraints +## Usability Constraints + +**Aggregation:** When aggregating Pricing Quantity for commitment utilization calculations, it's important to exclude *commitment discount* purchases (i.e. when *ChargeCategory* is "Purchase") that are paid to cover future eligible charges (e.g., *Commitment Discount*). Otherwise, when accounting for all upfront or accrued purchases, it's important to exclude *commitment discount* usage (i.e. when *ChargeCategory* is "Usage"). This exclusion helps prevent double counting of these quantities in the aggregation. + +## Content Constraints | Constraint | Value | |:----------------|:--------------------------| From f4a26ecaf11252d39bff548c7e01cc73193bfc69 Mon Sep 17 00:00:00 2001 From: Joaquin Date: Tue, 8 Oct 2024 15:49:30 -0700 Subject: [PATCH 46/52] Editorial changes to columns names and ids (#588) _The changes in this PR are in accordance with the agreement that we will continue to use the previous version of the editorial guidelines in FOCUS version 1.1 (for details, see the table below)._
      Component Markdown (examples) Editorial Guidelines
      Column Names: Column Names:
      Pricing Quantity
      Pricing Unit
      Provider
      • Normal text without bold or italics.
      • Use the display name in the introductory (non-normative) section and description.
      • The first occurrence in a section is linked to the section, except when referring to itself.
      Attribute Names: Attribute Names:
      Currency Code Format
      Date/Time Format
      • Normal text without bold or italics.
      • Use the attribute display name in the introductory (non-normative) section, description, normative section, and content constraints table.
      • The first occurrence in a section is linked to the section, except when referring to itself.
      Column IDs: Column IDs:
      PricingQuantity
      PricingUnit
      ProviderName
      • Normal text without bold or italics.
      • Use the column ID in the normative section and when referencing column values.
      • For column IDs, use PascalCase (the first letter of every word is capitalized).
      • The first occurrence in a section is linked to the corresponding column, except when referring to itself.
      Glossary [*SKU*](#glossary:sku)
      [*resource*](#glossary:resource)
      [*service*](#glossary:service)
      • Italic.
      • The first occurrence in a section is linked to the glossary term.
      --------- Co-authored-by: Irena Jurica --- specification/columns/skupricedetails.md | 28 ++++++++++++------------ specification/columns/skupriceid.md | 16 +++++++------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/specification/columns/skupricedetails.md b/specification/columns/skupricedetails.md index fc4cb984e..a8f8381c3 100644 --- a/specification/columns/skupricedetails.md +++ b/specification/columns/skupricedetails.md @@ -1,22 +1,22 @@ # SKU Price Details -The **SKU Price Details** column represents a list of relevant properties shared by all charges with the same [**SKU Price ID**](#skupriceid). These properties provide qualitative and quantitative details about the service represented by a **SKU Price ID**. This can enable practitioners to calculate metrics such as total units of a service when it is not directly billed in those units (e.g. cores) and thus enables FinOps capabilities such as unit economics. These properties can also help a practitioner understand the specifics of a **SKU Price ID** and differentiate it other **SKU Price IDs**. +The SKU Price Details column represents a list of relevant properties shared by all charges with the same [SKU Price ID](#skupriceid). These properties provide qualitative and quantitative details about the service represented by a SKU Price ID. This can enable practitioners to calculate metrics such as total units of a service when it is not directly billed in those units (e.g. cores) and thus enables FinOps capabilities such as unit economics. These properties can also help a practitioner understand the specifics of a SKU Price ID and differentiate it other SKU Price IDs. -The *SkuPriceDetails* column adheres to the following requirements: +The SkuPriceDetails column adheres to the following requirements: -* The *SkuPriceDetails* column MUST be in [*KeyValueFormat*](#key-valueformat). +* The SkuPriceDetails column MUST be in [KeyValueFormat](#key-valueformat). * The key for a property SHOULD be formatted in [PascalCase](#glossary:pascalcase). -* The properties (both keys and values) contained in the *SkuPriceDetails* column MUST be shared across all charges having the same *SkuPriceId*, subject to the below provisions. - * Additional properties (key-value pairs) MAY be added to *SkuPriceDetails* going forward for a given *SkuPriceId*. - * Properties SHOULD NOT be removed from *SkuPriceDetails* for a given *SkuPriceId*, once they have been included. - * Individual properties (key-value pairs) SHOULD NOT be modified for a given *SkuPriceId* and SHOULD remain consistent over time. +* The properties (both keys and values) contained in the SkuPriceDetails column MUST be shared across all charges having the same SkuPriceId, subject to the below provisions. + * Additional properties (key-value pairs) MAY be added to SkuPriceDetails going forward for a given SkuPriceId. + * Properties SHOULD NOT be removed from SkuPriceDetails for a given SkuPriceId, once they have been included. + * Individual properties (key-value pairs) SHOULD NOT be modified for a given SkuPriceId and SHOULD remain consistent over time. * The key for a property SHOULD remain consistent across comparable SKUs having that property and the values for this key SHOULD remain in a consistent format. -* The *SkuPriceDetails* column MUST NOT contain properties which are not applicable to the corresponding *SkuPriceId*. -* The *SkuPriceDetails* column MAY contain properties which are already captured in other dedicated columns. -* If a property has a numeric value, it MUST represent the value for a single [*PricingUnit*](#pricingunit). -* The *SkuPriceDetails* column MUST be present in the billing data when the provider includes a *SkuPriceId*. - * The *SkuPriceDetails* column MAY be null when *SkuPriceId* is not null. - * The *SkuPriceDetails* column MUST be null when *SkuPriceId* is null. +* The SkuPriceDetails column MUST NOT contain properties which are not applicable to the corresponding SkuPriceId. +* The SkuPriceDetails column MAY contain properties which are already captured in other dedicated columns. +* If a property has a numeric value, it MUST represent the value for a single [PricingUnit](#pricingunit). +* The SkuPriceDetails column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider includes a SkuPriceId. + * The SkuPriceDetails column MAY be null when SkuPriceId is not null. + * The SkuPriceDetails column MUST be null when SkuPriceId is null. ## Examples @@ -39,7 +39,7 @@ SKU Price Details ## Description -A set of properties of a **SKU Price ID** which are meaningful and common to all instances of that **SKU Price ID**. +A set of properties of a SKU Price ID which are meaningful and common to all instances of that SKU Price ID. ## Content Constraints diff --git a/specification/columns/skupriceid.md b/specification/columns/skupriceid.md index dfbc94b54..69bf70a87 100644 --- a/specification/columns/skupriceid.md +++ b/specification/columns/skupriceid.md @@ -2,14 +2,14 @@ A SKU Price ID is a unique identifier that defines the unit price used to calculate the charge. SKU Price ID can be referenced on a [*price list*](#glossary:price-list) published by a provider to look up detailed information, including a corresponding list unit price. The composition of the properties associated with the SKU Price ID may differ across providers. SKU Price ID is commonly used for analyzing cost based on pricing properties such as Terms and Tiers. -The *SkuPriceId* column adheres to the following requirements: - -* *SkuPriceId* MUST be present in a FOCUS dataset when the provider publishes a SKU price list and MUST be of type String. -* *SkuPriceId* MUST define a single unit price used for calculating the charge. -* [*ListUnitPrice*](#listunitprice) MUST be associated with the *SkuPriceId* in the provider published price list. -* *SkuPriceId* MUST NOT be null when [*ChargeClass*](#chargeclass) is not "Correction" and [*ChargeCategory*](#chargecategory) is "Usage" or "Purchase", MUST be null when *ChargeCategory* is "Tax", and MAY be null for all other combinations of *ChargeClass* and *ChargeCategory*. -* A given value of *SkuPriceId* MUST be associated with one and only one [*SkuId*](#skuid), except in cases of [*commitment discount flexibility*](glossary:commitment-discount-flexibility). -* If a provider does not have a *SkuPriceId* and wants to include information in columns linked to *SkuPriceId* such as *ListUnitPrice* or [*SkuPriceDetails*](#skupricedetails), the *SkuId* MAY be used in the *SkuPriceId* column as long as it adheres to the above conditions. +The SkuPriceId column adheres to the following requirements: + +* SkuPriceId MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider publishes a SKU price list and MUST be of type String. +* SkuPriceId MUST define a single unit price used for calculating the charge. +* [ListUnitPrice](#listunitprice) MUST be associated with the SkuPriceId in the provider published price list. +* SkuPriceId MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. +* A given value of SkuPriceId MUST be associated with one and only one [SkuId](#skuid), except in cases of [commitment discount flexibility](#glossary:commitment-discount-flexibility). +* If a provider does not have a SkuPriceId and wants to include information in columns linked to SkuPriceId such as ListUnitPrice or [SkuPriceDetails](#skupricedetails), the SkuId MAY be used in the SkuPriceId column as long as it adheres to the above conditions. ## Column ID From 5f123bd8e9f643c26527f4228b05b862af89d656 Mon Sep 17 00:00:00 2001 From: Irena Jurica Date: Wed, 9 Oct 2024 00:49:55 +0200 Subject: [PATCH 47/52] Editorial changes to columns names and ids (part 2) (#589) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _The changes in this PR are in accordance with the agreement that we will continue to use the previous version of the editorial guidelines in FOCUS version 1.1 (for details, see the table below)._
      Component Markdown (examples) Editorial Guidelines
      Column Names: Column Names:
      Pricing Quantity
      Pricing Unit
      Provider
      • Normal text without bold or italics.
      • Use the display name in the introductory (non-normative) section and description.
      • The first occurrence in a section is linked to the section, except when referring to itself.
      Attribute Names: Attribute Names:
      Currency Code Format
      Date/Time Format
      • Normal text without bold or italics.
      • Use the attribute display name in the introductory (non-normative) section, description, normative section, and content constraints table.
      • The first occurrence in a section is linked to the section, except when referring to itself.
      Column IDs: Column IDs:
      PricingQuantity
      PricingUnit
      ProviderName
      • Normal text without bold or italics.
      • Use the column ID in the normative section and when referencing column values.
      • For column IDs, use PascalCase (the first letter of every word is capitalized).
      • The first occurrence in a section is linked to the corresponding column, except when referring to itself.
      Glossary [*SKU*](#glossary:sku)
      [*resource*](#glossary:resource)
      [*service*](#glossary:service)
      • Italic.
      • The first occurrence in a section is linked to the glossary term.
      --- **Types of Editorial Changes:** - Aligned the **formatting** of references to columns (display name, ID) and glossary terms with the approach used in other columns. - Aligned **formatting of references to format attributes** in normative requirements, opting for the **attribute name instead of the attribute ID** (_see Note for reasoning_): - CommitmentDiscountUnit, ConsumedUnit and PricingUnit addressed in this PR - SkuPriceDetails addressed in PR #588 - Addressed several **missing and broken links** to columns and glossary terms. **Changes applied to the following columns:** - Commitment Discount Quantity - Commitment Discount Unit - Consumed Unit - Pricing Unit - Service Subcategory --- **Notes:** - I prefer using the attribute name over the attribute ID when referencing formatting attributes, at least for now, considering: - The attribute name was used in the Content Constraints tables in all instances. - The attribute name was used in the Normative Requirements in 13 instances. - The attribute ID was used in the Normative Requirements in only 4 instances (CommitmentDiscountUnit, ConsumedUnit, PricingUnit, SkuPriceDetails). - In 2 instances (ChargePeriodStart and ChargePeriodEnd), although listed in the constraints table, the requirement to follow the Date/Time format wasn’t explicitly mentioned in the normative requirements paragraph. I suggest addressing all Date/Time references in version 1.2 or later. --- .../columns/commitmentdiscountquantity.md | 24 +++++++++---------- .../columns/commitmentdiscountunit.md | 10 ++++---- specification/columns/pricingunit.md | 2 +- specification/columns/servicesubcategory.md | 2 +- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/specification/columns/commitmentdiscountquantity.md b/specification/columns/commitmentdiscountquantity.md index b78b40965..464bc2dfe 100644 --- a/specification/columns/commitmentdiscountquantity.md +++ b/specification/columns/commitmentdiscountquantity.md @@ -1,24 +1,24 @@ # Commitment Discount Quantity -Commitment Discount Quantity is the amount of a [*commitment discount*](#commitment-discount) purchased or accounted for in *commitment discount* related [*rows*](#glossary:row) that is denominated in [*Commitment Discount Units*](#glossary:commitmentdiscountunit). The aggregated Commitment Discount Quantity across purchase records, pertaining to a particular [Commitment Discount ID](#commitmentdiscountid) during its [*term*](#glossary:term), represents the total *Commitment Discount Units* acquired with that commitment discount. For committed usage, the Commitment Discount Quantity is either the number of *Commitment Discount Units* consumed by a [*row*](glossary:#row) that is covered by a *commitment discount* or is the unused portion of a *commitment discount* over a *charge period*. Commitment Discount Quantity is commonly used in *commitment discount* analysis and optimization use cases and only applies to *commitment discounts*, not [*negotiated discounts*](#glossary:negotiated-discount). +Commitment Discount Quantity is the amount of a [*commitment discount*](#glossary:commitment-discount) purchased or accounted for in *commitment discount* related [*rows*](#glossary:row) that is denominated in [Commitment Discount Units](#commitmentdiscountunit). The aggregated Commitment Discount Quantity across purchase records, pertaining to a particular [Commitment Discount ID](#commitmentdiscountid) during its [*term*](#glossary:term), represents the total Commitment Discount Units acquired with that commitment discount. For committed usage, the Commitment Discount Quantity is either the number of Commitment Discount Units consumed by a *row* that is covered by a *commitment discount* or is the unused portion of a *commitment discount* over a *charge period*. Commitment Discount Quantity is commonly used in *commitment discount* analysis and optimization use cases and only applies to *commitment discounts*, not [*negotiated discounts*](#glossary:negotiated-discount). -When *CommitmentDiscountCategory* is "Usage" (usage-based *commitment discounts*), the Commitment Discount Quantity reflects the predefined amount of usage purchased or consumed. If [*commitment discount flexibility*](glossary:commitment-discount-flexibility) is applicable, this value may be further transformed based on additional, provider-specific requirements. When *CommitmentDiscountCategory* is "Spend" (spend-based *commitment discounts*), the Commitment Discount Quantity reflects the predefined amount of spend purchased or consumed. +When [CommitmentDiscountCategory](#commitmentdiscountcategory) is "Usage" (usage-based *commitment discounts*), the Commitment Discount Quantity reflects the predefined amount of usage purchased or consumed. If [*commitment discount flexibility*](#glossary:commitment-discount-flexibility) is applicable, this value may be further transformed based on additional, provider-specific requirements. When CommitmentDiscountCategory is "Spend" (spend-based *commitment discounts*), the Commitment Discount Quantity reflects the predefined amount of spend purchased or consumed. The CommitmentDiscountQuantity column adheres to the following requirements: * CommitmentDiscountQuantity MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. -* CommitmentDiscountQuantity MUST be of type Decimal and MUST conform to [Numeric Format](#numericformat) requirements. -* CommitmentDiscountQuantity MAY be null or any valid decimal value if [*CommitmentDiscountId*](#commitmentdiscountid) is not null and [*ChargeClass*](#chargeclass) is "Correction". +* CommitmentDiscountQuantity MUST be of type Decimal and MUST conform to [NumericFormat](#numericformat) requirements. +* CommitmentDiscountQuantity MAY be null or any valid decimal value if [CommitmentDiscountId](#commitmentdiscountid) is not null and [ChargeClass](#chargeclass) is "Correction". -In cases where the *ChargeCategory* is "Purchase", *CommitmentDiscountId* is not null, and *ChargeClass* is not "Correction", the following applies: +In cases where the ChargeCategory is "Purchase", CommitmentDiscountId is not null, and ChargeClass is not "Correction", the following applies: -* When [*ChargeFrequency*](#chargefrequency) is "One-Time", and *CommitmentDiscountId* is not null, CommitmentDiscountQuantity MUST be the positive quantity of *CommitmentDiscountUnits*, paid fully or partially upfront, that is eligible for consumption over the *commitment discount's* *term*. -* When *ChargeFrequency* is "Recurring", and *CommitmentDiscountId* is not null, CommitmentDiscountQuantity MUST be the positive quantity of *CommitmentDiscountUnits* that is eligible for consumption for each *charge period* that corresponds with the purchase. +* When [ChargeFrequency](#chargefrequency) is "One-Time", and CommitmentDiscountId is not null, CommitmentDiscountQuantity MUST be the positive quantity of CommitmentDiscountUnits, paid fully or partially upfront, that is eligible for consumption over the *commitment discount's* *term*. +* When ChargeFrequency is "Recurring", and CommitmentDiscountId is not null, CommitmentDiscountQuantity MUST be the positive quantity of CommitmentDiscountUnits that is eligible for consumption for each *charge period* that corresponds with the purchase. -In cases where the *ChargeCategory* is "Usage", *CommitmentDiscountId* is not null, and *ChargeClass* is not "Correction", the following applies: +In cases where the ChargeCategory is "Usage", CommitmentDiscountId is not null, and ChargeClass is not "Correction", the following applies: -* When *CommitmentDiscountStatus* is "Used", CommitmentDiscountQuantity MUST be the positive, metered quantity of *CommitmentDiscountUnits* that is consumed over the *row's* *charge period*. -* When *CommitmentDiscountStatus* is "Unused", CommitmentDiscountQuantity MUST be the remaining, positive, unused quantity of *CommitmentDiscountUnits* for the *row's* *charge period*. +* When [CommitmentDiscountStatus](#commitmentdiscountstatus) is "Used", CommitmentDiscountQuantity MUST be the positive, metered quantity of CommitmentDiscountUnits that is consumed over the *row's* *charge period*. +* When CommitmentDiscountStatus is "Unused", CommitmentDiscountQuantity MUST be the remaining, positive, unused quantity of CommitmentDiscountUnits for the *row's* *charge period*. CommitmentDiscountQuantity MUST be null in all other cases. @@ -32,11 +32,11 @@ Commitment Discount Quantity ## Description -The amount of a *commitment discount* purchased or accounted for in *commitment discount* related *rows* that is denominated in *Commitment Discount Units*. +The amount of a *commitment discount* purchased or accounted for in *commitment discount* related *rows* that is denominated in Commitment Discount Units. ## Usability Constraints -**Aggregation:** When aggregating Commitment Discount Quantity for commitment utilization calculations, it's important to exclude *commitment discount* purchases (i.e. when *ChargeCategory* is "Purchase") that are paid to cover future eligible charges (e.g., *Commitment Discount*). Otherwise, when accounting for all upfront or accrued purchases, it's important to exclude *commitment discount* usage (i.e. when *ChargeCategory* is "Usage"). This exclusion helps prevent double counting of these quantities in the aggregation. +**Aggregation:** When aggregating Commitment Discount Quantity for commitment utilization calculations, it's important to exclude *commitment discount* purchases (i.e. when ChargeCategory is "Purchase") that are paid to cover future eligible charges (e.g., *commitment discount*). Otherwise, when accounting for all upfront or accrued purchases, it's important to exclude *commitment discount* usage (i.e. when ChargeCategory is "Usage"). This exclusion helps prevent double counting of these quantities in the aggregation. ## Content constraints diff --git a/specification/columns/commitmentdiscountunit.md b/specification/columns/commitmentdiscountunit.md index fc91838b1..e64a03a5c 100644 --- a/specification/columns/commitmentdiscountunit.md +++ b/specification/columns/commitmentdiscountunit.md @@ -6,15 +6,15 @@ The CommitmentDiscountUnit column adheres to the following requirements: * CommitmentDiscountUnit MUST be present in a FOCUS dataset when the provider supports [*commitment discounts*](#glossary:commitment-discount). * CommitmentDiscountUnit MUST be of type String, and the units of measure used in CommitmentDiscountUnit SHOULD adhere to the values and format requirements specified in the [UnitFormat](#unitformat) attribute. -* The CommitmentDiscountUnit MUST be the same across all *rows* where *CommitmentDiscountQuantity* has the same [*CommitmentDiscountId*](#commitmentdiscountid). -* CommitmentDiscountUnit MAY be null if [*CommitmentDiscountId*](#commitmentdiscountid) is not null and [*ChargeClass*](#chargeclass) is "Correction". -* CommitmentDiscountUnit MUST NOT be null when *CommitmentDiscountId* is not null and *ChargeClass* is not "Correction". +* The CommitmentDiscountUnit MUST be the same across all *rows* where CommitmentDiscountQuantity has the same [CommitmentDiscountId](#commitmentdiscountid). +* CommitmentDiscountUnit MAY be null if CommitmentDiscountId is not null and [ChargeClass](#chargeclass) is "Correction". +* CommitmentDiscountUnit MUST NOT be null when CommitmentDiscountId is not null and ChargeClass is not "Correction". * CommitmentDiscountUnit MUST be null in all other cases. In cases where the CommitmentDiscountUnit is not null, the following applies: * The CommitmentDiscountUnit MUST represent the unit used to measure the *commitment discount*. -* When accounting for [*commitment discount flexibility*](glossary:commitment-discount-flexibility), the CommitmentDiscountUnit value SHOULD reflect this consideration. +* When accounting for [*commitment discount flexibility*](#glossary:commitment-discount-flexibility), the CommitmentDiscountUnit value SHOULD reflect this consideration. ## Column ID @@ -26,7 +26,7 @@ Commitment Discount Unit ## Description -The provider-specified measurement unit indicating how a provider measures the *Commitment Discount Quantity* of a *commitment discount*. +The provider-specified measurement unit indicating how a provider measures the Commitment Discount Quantity of a *commitment discount*. ## Content constraints diff --git a/specification/columns/pricingunit.md b/specification/columns/pricingunit.md index 3b4fca8db..dccea8655 100644 --- a/specification/columns/pricingunit.md +++ b/specification/columns/pricingunit.md @@ -2,7 +2,7 @@ The Pricing Unit represents a provider-specified measurement unit for determining unit prices, indicating how the provider rates measured usage and purchase quantities after applying pricing rules like [*block pricing*](#glossary:block-pricing). Common examples include the number of hours for compute appliance runtime (e.g. `Hours`), gigabyte-hours for a storage appliance (e.g., `GB-Hours`), or an accumulated count of requests for a network appliance or API service (e.g., `1000 Requests`). Pricing Unit complements the [Pricing Quantity](#pricingquantity) metric. Distinct from the [Consumed Unit](#consumedunit), it focuses on pricing and cost, not [*resource*](#glossary:resource) and [*service*](#glossary:service) consumption, often at a coarser granularity. -The PricingUnit column MUST be present in a FOCUS dataset. This column MUST be of type String. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. Units of measure used in PricingUnit SHOULD adhere to the values and format requirements specified in the [UnitFormat](#unitformat) attribute. +The PricingUnit column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset). This column MUST be of type String. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. Units of measure used in PricingUnit SHOULD adhere to the values and format requirements specified in the [UnitFormat](#unitformat) attribute. The PricingUnit value MUST be semantically equal to the corresponding pricing measurement unit value provided in: diff --git a/specification/columns/servicesubcategory.md b/specification/columns/servicesubcategory.md index c353d039f..f235967fb 100644 --- a/specification/columns/servicesubcategory.md +++ b/specification/columns/servicesubcategory.md @@ -1,6 +1,6 @@ # Service Subcategory -The Service Subcategory is a secondary classification of the Service Category for a [*service*](#glossary:service) based on its core function. The Service Subcategory (in conjunction with the Service Category) is commonly used for scenarios like analyzing spend and usage for specific workload types across providers and tracking the migration of workloads across fundamentally different architectures. +The Service Subcategory is a secondary classification of the [Service Category](#servicecategory) for a [*service*](#glossary:service) based on its core function. The Service Subcategory (in conjunction with the Service Category) is commonly used for scenarios like analyzing spend and usage for specific workload types across providers and tracking the migration of workloads across fundamentally different architectures. The ServiceSubcategory column adheres to the following requirements: From 7971283e6591b288143dc39e13966a34ed07f332 Mon Sep 17 00:00:00 2001 From: Irena Jurica Date: Wed, 9 Oct 2024 00:50:30 +0200 Subject: [PATCH 48/52] Editorial changes to appendix - links to columns and glossary terms (#590) Editorial changes: - Commitment Discounts - Replaced column names previously formatted as code with links to columns - Addressed several missing and broken links to glossary terms - Grouping Constructs for Resources or Services - Added links to billing account, sub account, resource and service glossary terms - Origination of Cost Data - Added links to Provider, Publisher and Invoice Issuer columns - Added links to resource and service glossary terms --- _The changes in this PR are in accordance with the agreement that we will continue to use the previous version of the editorial guidelines in FOCUS version 1.1 (for details, see the table below)._
      Component Markdown (examples) Editorial Guidelines
      Column Names: Column Names:
      Pricing Quantity
      Pricing Unit
      Provider
      • Normal text without bold or italics.
      • Use the display name in the introductory (non-normative) section and description.
      • The first occurrence in a section is linked to the section, except when referring to itself.
      Attribute Names: Attribute Names:
      Currency Code Format
      Date/Time Format
      • Normal text without bold or italics.
      • Use the attribute display name in the introductory (non-normative) section, description, normative section, and content constraints table.
      • The first occurrence in a section is linked to the section, except when referring to itself.
      Column IDs: Column IDs:
      PricingQuantity
      PricingUnit
      ProviderName
      • Normal text without bold or italics.
      • Use the column ID in the normative section and when referencing column values.
      • For column IDs, use PascalCase (the first letter of every word is capitalized).
      • The first occurrence in a section is linked to the corresponding column, except when referring to itself.
      Glossary [*SKU*](#glossary:sku)
      [*resource*](#glossary:resource)
      [*service*](#glossary:service)
      • Italic.
      • The first occurrence in a section is linked to the glossary term.
      --- specification/appendix/commitment_discounts.md | 16 ++++++++-------- ...g_constructs_for_resources_and_or_services.md | 6 +++--- .../appendix/origination_of_cost_data.md | 8 ++++---- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/specification/appendix/commitment_discounts.md b/specification/appendix/commitment_discounts.md index ed4733c68..243502a74 100644 --- a/specification/appendix/commitment_discounts.md +++ b/specification/appendix/commitment_discounts.md @@ -1,17 +1,17 @@ # Commitment Discounts -A [*commitment discount*](glossary:commitment-discount) is a billing discount model that offers reduced rates on preselected [*SKUs*](#glossary:sku) in exchange for an obligated usage or spend amount over a predefined [*term*](glossary:term). *Commitment discounts* typically consist of purchase and usage records within cost and usage datasets. +A [*commitment discount*](#glossary:commitment-discount) is a billing discount model that offers reduced rates on preselected [*SKUs*](#glossary:sku) in exchange for an obligated usage or spend amount over a predefined [*term*](#glossary:term). *Commitment discounts* typically consist of purchase and usage records within cost and usage datasets. -Usage-based *commitment discounts* obligate a customer to a predetermined amount of usage over a preselected *term*. In some cases, usage-based *commitment discounts* also feature [*commitment discount flexibility*](glossary:commitment-discount-flexibility) which may expand the types of *resources* that a *commitment discount* can cover. It is important to note when mixing *commitment discounts* with and without *commitment discount flexibility*, the `CommitmentDiscountUnit` should reflect this difference. +Usage-based *commitment discounts* obligate a customer to a predetermined amount of usage over a preselected *term*. In some cases, usage-based *commitment discounts* also feature [*commitment discount flexibility*](#glossary:commitment-discount-flexibility) which may expand the types of [*resources*](#glossary:resource) that a *commitment discount* can cover. It is important to note when mixing *commitment discounts* with and without *commitment discount flexibility*, the [CommitmentDiscountUnit](#commitmentdiscountunit) should reflect this difference. -Spend-based commitment discounts obligate a customer to a predetermined amount of spend over a preselected *term*. In the usage examples below, each [*row*](glossary:row) measures the monetary amount of the hourly commit consumed by the *commitment discount*, so the `CommitmentDiscountUnit` chosen is "USD", or the [*billing currency*](glossary:billing-currency). +Spend-based commitment discounts obligate a customer to a predetermined amount of spend over a preselected *term*. In the usage examples below, each [*row*](#glossary:row) measures the monetary amount of the hourly commit consumed by the *commitment discount*, so the CommitmentDiscountUnit chosen is "USD", or the [*billing currency*](#glossary:billing-currency). ## Purchasing While customers are bound to the *term* of a *commitment discounts*, providers offer some or all of the following payment options before and/or during the *term*: * *All Upfront* - The *commitment discounts* is paid in full before the *term* begins. -* *No Upfront* - The *commitment discounts* is paid on a repeated basis, typically over each [*billing period*](glossary:billing-period) of the *term*. +* *No Upfront* - The *commitment discounts* is paid on a repeated basis, typically over each [*billing period*](#glossary:billing-period) of the *term*. * *Partial Upfront* - Some of the *commitment discounts* is paid before the *term* begins, and the rest is paid repeatedly over the *term*. For example, if a customer buys a 1-year, spend-based *commitment discount* with a $1.00 hourly commit and pays with the partial option, the *commitment discount's* payment consists of a one-time purchase in the beginning of the *term* *and* monthly recurring purchases with the following totals: @@ -21,7 +21,7 @@ For example, if a customer buys a 1-year, spend-based *commitment discount* with ## Usage -Commitment discounts follow a "use-it-or-lose-it" model where the [*amortization*](glossary:amortization) of a *commitment discount's* purchase applies evenly to eligible *resources* over each [*charge period*](glossary:charge-period) of the *term*. +Commitment discounts follow a "use-it-or-lose-it" model where the [*amortization*](#glossary:amortization) of a *commitment discount's* purchase applies evenly to eligible *resources* over each [*charge period*](#glossary:charge-period) of the *term*. For example, if a customer buys a spend-based *commitment discount* with a $1.00 hourly commit in January (31 days), only $1.00 is eligible for consumption for each hourly *charge period*. If a customer has eligible *resources* running during this *charge period*, an amount of up to $1.00 will be allocated to these *resources*. Conversely, if a customer does have eligible *resources* running that fully take advantage of this $1.00 during this *charge period*, then some or all of this amount will go to waste. @@ -31,9 +31,9 @@ Within the FOCUS specification, the following examples demonstrate how a *commit ### Purchase *Rows* -All *commitment discount* purchases appear with a positive `BilledCost`, `PricingCategory` as "Standard", and with the *commitment discount's* id populating both the `ResourceId` and `CommitmentDiscountId` value. One-time purchases appear as a single record with `ChargeCategory` as "Purchase", `ChargeFrequency` as "One-Time", and the total quantity and units for *commitment discount's* *term* reflected as `CommitmentDiscountQuantity` and `CommitmentDiscountUnit`, respectively. +All *commitment discount* purchases appear with a positive [BilledCost](#billedcost), [PricingCategory](#pricingcategory) as "Standard", and with the *commitment discount's* id populating both the [ResourceId](#resourceid) and [CommitmentDiscountId](#commitmentdiscountid) value. One-time purchases appear as a single record with [ChargeCategory](#chargecategory) as "Purchase", [ChargeFrequency](#chargefrequency) as "One-Time", and the total quantity and units for *commitment discount's* *term* reflected as [CommitmentDiscountQuantity](#commitmentdiscountquantity) and CommitmentDiscountUnit, respectively. -Recurring purchases are allocated across all corresponding *charge periods* of the *term* when `ChargeCategory` is "Purchase", `ChargeFrequency` is "Recurring", and `CommitmentDiscountQuantity` and `CommitmentDiscountUnit` are reflected only for that *charge period*. +Recurring purchases are allocated across all corresponding *charge periods* of the *term* when ChargeCategory is "Purchase", ChargeFrequency is "Recurring", and CommitmentDiscountQuantity and CommitmentDiscountUnit are reflected only for that *charge period*. Using the same *commitment discount* example as above with a one-year, spend-based *commitment discount* with a $1.00 hourly commit purchased on Jan 1, 2023, various purchase options are available: @@ -166,7 +166,7 @@ In this scenario, one eligible *resource* runs for the full hour and consumes &d #### Scenario #2: No eligible *resource* consumes the allocated amount (0% utilization) -In this situation, the full eligible, $1.00 amount remained unutilized and results in 1 unused *row*. In this scenario, it is important to note that while `CommitmentDiscountQuantity` is not because $1 was still drawn down by the *commitment discount* even though, no *resource* was allocated, so `ConsumedQuantity` and `ConsumedUnit` are null. +In this situation, the full eligible, $1.00 amount remained unutilized and results in 1 unused *row*. In this scenario, it is important to note that while CommitmentDiscountQuantity is not because $1 was still drawn down by the *commitment discount* even though, no *resource* was allocated, so [ConsumedQuantity](#consumedquantity) and [ConsumedUnit](#consumedunit) are null. ```json [ diff --git a/specification/appendix/grouping_constructs_for_resources_and_or_services.md b/specification/appendix/grouping_constructs_for_resources_and_or_services.md index 76bb5b994..3fb69f94f 100644 --- a/specification/appendix/grouping_constructs_for_resources_and_or_services.md +++ b/specification/appendix/grouping_constructs_for_resources_and_or_services.md @@ -1,11 +1,11 @@ # Grouping constructs for resources or services -Providers natively support various constructs for grouping resources or services. These grouping constructs are often used to mimic organizational structures, technical architectures, cost attribution/allocation and access management boundaries, or other customer-specific structures based on requirements. +Providers natively support various constructs for grouping [*resources*](#glossary:resource) or [*services*](#glossary:service). These grouping constructs are often used to mimic organizational structures, technical architectures, cost attribution/allocation and access management boundaries, or other customer-specific structures based on requirements. Providers may support multiple levels of resource or service grouping mechanisms. FOCUS supports two distinct levels of groupings that are commonly needed for FinOps capabilities like chargeback, invoice reconciliation and cost allocation. -* Billing account: A mandatory container for resources or services that are billed together in an invoice. Billing accounts are commonly used for scenarios like grouping based on organizational constructs, invoice reconciliation and cost allocation strategies. -* Sub account: An optional provider-supported construct for organizing resources and services connected to a billing account. Sub accounts are commonly used for scenarios like grouping based on organizational constructs, access management needs and cost allocation strategies. Sub accounts must be associated with a billing account as they do not receive invoices. +* [*Billing account*](#glossary:billing-account): A mandatory container for *resources* or *services* that are billed together in an invoice. *Billing accounts* are commonly used for scenarios like grouping based on organizational constructs, invoice reconciliation and cost allocation strategies. +* [Sub account](#glossary:sub-account): An optional provider-supported construct for organizing *resources* and *services* connected to a *billing account*. *Sub accounts* are commonly used for scenarios like grouping based on organizational constructs, access management needs and cost allocation strategies. *Sub accounts* must be associated with a *billing account* as they do not receive invoices. The table below highlights key properties of the two grouping constructs supported by FOCUS. diff --git a/specification/appendix/origination_of_cost_data.md b/specification/appendix/origination_of_cost_data.md index 55ed959ba..4d5ffe239 100644 --- a/specification/appendix/origination_of_cost_data.md +++ b/specification/appendix/origination_of_cost_data.md @@ -2,11 +2,11 @@ Cost data presented in the billing datasets originates from various sources depending on the purchasing mechanism. There are at least 3 different pieces of information that are important for understanding where cost originated from. -* Provider: The entity that made the resources or services available for purchase. -* Publisher: The entity that produced the resources or services that were purchased. -* Invoice Issuer: The entity responsible for invoicing for the resources or services consumed. +* [Provider](#provider): The entity that made the [*resources*](#glossary:resource) or [*services*](#glossary:service) available for purchase. +* [Publisher](#publisher): The entity that produced the *resources* or *services* that were purchased. +* [Invoice Issuer](#invoiceissuer): The entity responsible for invoicing for the *resources* or *services* consumed. -The value for each of these may be different depending on the various purchasing scenarios for resources or services. Use cases for purchasing direct, via a Managed Service Provider (MSP), via a cloud marketplace, and from internal service offerings were considered. The table below presents a few scenarios to show how the value for each dimension may change based on the purchasing scenario. +The value for each of these may be different depending on the various purchasing scenarios for *resources* or *services*. Use cases for purchasing direct, via a Managed Service Provider (MSP), via a cloud marketplace, and from internal service offerings were considered. The table below presents a few scenarios to show how the value for each dimension may change based on the purchasing scenario. | # | Scenario | Provider | Publisher | Invoice Issuer | |:----|:----------------------------------------------------------------------------------------------------------------------------------------------|:-------------------------|:-----------------------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------| From 16e9b1cf168bf7a4189e39d7f4f93146deb88995 Mon Sep 17 00:00:00 2001 From: Irena Jurica Date: Wed, 9 Oct 2024 00:51:04 +0200 Subject: [PATCH 49/52] Editorial changes to columns and glossary terms ordering (#591) Editorial changes (ordering): - Columns - Glossary terms --- specification/columns/columns.mdpp | 2 +- specification/glossary.md | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/specification/columns/columns.mdpp b/specification/columns/columns.mdpp index c1dc78124..48cbb79f4 100644 --- a/specification/columns/columns.mdpp +++ b/specification/columns/columns.mdpp @@ -20,9 +20,9 @@ The FOCUS specification defines a group of columns that provide qualitative valu !INCLUDE "commitmentdiscountcategory.md",1 !INCLUDE "commitmentdiscountid.md",1 !INCLUDE "commitmentdiscountname.md",1 +!INCLUDE "commitmentdiscountquantity.md",1 !INCLUDE "commitmentdiscountstatus.md",1 !INCLUDE "commitmentdiscounttype.md",1 -!INCLUDE "commitmentdiscountquantity.md",1 !INCLUDE "commitmentdiscountunit.md",1 !INCLUDE "consumedquantity.md",1 !INCLUDE "consumedunit.md",1 diff --git a/specification/glossary.md b/specification/glossary.md index c09626a3f..443971a6a 100644 --- a/specification/glossary.md +++ b/specification/glossary.md @@ -44,6 +44,10 @@ A row in a FOCUS-compatible cost and usage dataset. The time window for which a charge is effective, inclusive of the start date and exclusive of the end date. The charge period for continuous usage should match the time granularity of the dataset (e.g., 1 hour for hourly, 1 day for daily). The charge period for a non-usage charge with time boundaries should match the duration of eligibility. +Cloud Service Provider (CSP) + +A company or organization that provides remote access to computing resources, infrastructure, or applications for a fee. + Commitment A customer's agreement to consume a specific quantity of a service or resource over a defined period, usually also creating a financial commitment throughout the entirety of the commitment period. Some commitments also hold Providers to certain assurance levels of resource availability. @@ -56,10 +60,6 @@ A billing discount model that offers reduced rates on preselected SKUs in exchan A feature of [*commitment discounts*](#glossary:commitment-discount) that may further transform the predetermined amount of usage purchased or consumed based on additional, provider-specific requirements. -Cloud Service Provider (CSP) - -A company or organization that provides remote access to computing resources, infrastructure, or applications for a fee. - Contracted Unit Price The agreed-upon unit price for a single [Pricing Unit](#pricingunit) of the associated SKU, inclusive of negotiated discounts, if present, and exclusive of any other discounts. This price is denominated in the [Billing Currency](#glossary:billingcurrency). @@ -100,14 +100,14 @@ A category of compute resources that can be paused or terminated by the CSP with The suggested provider-published unit price for a single [Pricing Unit](#pricingunit) of the associated [SKU](#glossary:sku), exclusive of any discounts. This price is denominated in the [Billing Currency](#glossary:billingcurrency). -Metric - -A FOCUS-defined column that provides numeric values, allowing for aggregation operations such as arithmetic operations (sum, multiplication, averaging etc.) and statistical operations. - Managed Service Provider (MSP) A company or organization that provides outsourced management and support of a range of IT services, such as network infrastructure, cybersecurity, cloud computing, and more. +Metric + +A FOCUS-defined column that provides numeric values, allowing for aggregation operations such as arithmetic operations (sum, multiplication, averaging etc.) and statistical operations. + Negotiated Discount A contractual agreement where a customer commits to specific spend or usage goals over a [*term*](#glossary:term) in exchange for discounted rates across varying SKUs. Unlike [*commitment discounts*](#glossary:commitment-discount), negotiated discounts are typically more customized to customer's accounts, can be utilized at varying frequencies, and may overlap with *commitment discounts*. @@ -120,22 +120,22 @@ A term that describes a service that is available and provided immediately or as Pascal Case (PascalCase, also known as UpperCamelCase) is a format for identifiers which contain one or more words meaning the words are concatenated together with no delimiter and the first letter of each word is capitalized. -Practitioner - -An individual who performs FinOps within an organization to maximize the business value of using cloud and cloud-like services. - Potato A long and often painful conversation had by the FOCUS contributors. Sometimes the name of a thing that we could not yet name. No starchy root vegetables were harmed during the production of this specification. We thank potato for its contribution in the creation of this specification. -Provider +Practitioner -An entity that made internal or 3rd party resources and/or services available for purchase. +An individual who performs FinOps within an organization to maximize the business value of using cloud and cloud-like services. Price List A comprehensive list of prices offered by a provider. +Provider + +An entity that made internal or 3rd party resources and/or services available for purchase. + Resource A unique component that incurs a charge. From 31276dd56269505d263e3a53d07c43737d27d428 Mon Sep 17 00:00:00 2001 From: Irena Jurica Date: Wed, 9 Oct 2024 01:08:19 +0200 Subject: [PATCH 50/52] Editorial changes: using attribute IDs when referencing attributes in normative paragraphs (#593) **Type of Editorial change:** Although attribute names were initially used for this purpose, for the sake of consistency and in accordance with the agreement made during the maintainers' meeting on Oct 8th, **switching from attribute names to attribute IDs in the normative paragraphs**, while retaining attribute names in the Content Constraints tables. **Scope of this PR:** This PR addresses references in the normative paragraphs of 12 columns and Metadata - CreationDate. For the remaining column, CommitmentDiscountQuantity, please refer to PR #589. --------- Co-authored-by: Joaquin --- specification/columns/billedcost.md | 2 +- specification/columns/billingcurrency.md | 2 +- specification/columns/billingperiodend.md | 2 +- specification/columns/billingperiodstart.md | 2 +- specification/columns/consumedquantity.md | 2 +- specification/columns/contractedcost.md | 2 +- specification/columns/contractedunitprice.md | 2 +- specification/columns/effectivecost.md | 2 +- specification/columns/listcost.md | 2 +- specification/columns/listunitprice.md | 2 +- specification/columns/pricingquantity.md | 2 +- specification/columns/tags.md | 2 +- specification/metadata/schema/creationdate.md | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/specification/columns/billedcost.md b/specification/columns/billedcost.md index da70e1d38..5daaa0285 100644 --- a/specification/columns/billedcost.md +++ b/specification/columns/billedcost.md @@ -2,7 +2,7 @@ The [*billed cost*](#glossary:billed-cost) represents a charge serving as the basis for invoicing, inclusive of the impacts of all reduced rates and discounts while excluding the [*amortization*](#glossary:amortization) of relevant purchases (one-time or recurring) paid to cover future eligible charges. This cost is denominated in the [Billing Currency](#billingcurrency). The Billed Cost is commonly used to perform FinOps capabilities that require cash-basis accounting such as cost allocation, budgeting, and invoice reconciliation. -The BilledCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat), and be denominated in the BillingCurrency. The sum of the BilledCost for [*rows*](#glossary:row) in a given [*billing period*](#glossary:billing-period) MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account). +The BilledCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [NumericFormat](#numericformat), and be denominated in the BillingCurrency. The sum of the BilledCost for [*rows*](#glossary:row) in a given [*billing period*](#glossary:billing-period) MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account). ## Column ID diff --git a/specification/columns/billingcurrency.md b/specification/columns/billingcurrency.md index 86ac91fa0..e60e127de 100644 --- a/specification/columns/billingcurrency.md +++ b/specification/columns/billingcurrency.md @@ -2,7 +2,7 @@ [*Billing currency*](#glossary:billing-currency) is an identifier that represents the currency that a charge for [*resources*](#glossary:resource) or [*services*](#glossary:service) was billed in. Billing Currency is commonly used in scenarios where costs need to be grouped or aggregated. -The BillingCurrency column MUST be present in a FOCUS dataset. BillingCurrency MUST match the currency used in the invoice generated by the invoice issuer. This column MUST be of type String and MUST NOT contain null values. BillingCurrency MUST conform to [Currency Code Format](#currencycodeformat) requirements. +The BillingCurrency column MUST be present in a FOCUS dataset. BillingCurrency MUST match the currency used in the invoice generated by the invoice issuer. This column MUST be of type String and MUST NOT contain null values. BillingCurrency MUST conform to [CurrencyCodeFormat](#currencycodeformat) requirements. ## Column ID diff --git a/specification/columns/billingperiodend.md b/specification/columns/billingperiodend.md index 9cd030e6d..fcd2cbaf2 100644 --- a/specification/columns/billingperiodend.md +++ b/specification/columns/billingperiodend.md @@ -2,7 +2,7 @@ Billing Period End represents the [*exclusive*](#glossary:exclusivebound) end date and time of a [*billing period*](#glossary:billing-period). For example, a time period where [BillingPeriodStart](#glossary:billingperiodstart) is '2024-01-01T00:00:00Z' and BillingPeriodEnd is '2024-02-01T00:00:00Z' includes charges for January, since BillingPeriodStart is [*inclusive*](#glossary:inclusivebound), but does not include charges for February since BillingPeriodEnd is *exclusive*. -The BillingPeriodEnd column MUST be present in a FOCUS dataset. This column MUST be of type [Date/Time Format](#date/timeformat), MUST be an *exclusive* value, and MUST NOT contain null values. The sum of the [BilledCost](#billedcost) column for [*rows*](#glossary:row) in a given *billing period* MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account). +The BillingPeriodEnd column MUST be present in a FOCUS dataset. This column MUST be of type [DateTimeFormat](#date/timeformat), MUST be an *exclusive* value, and MUST NOT contain null values. The sum of the [BilledCost](#billedcost) column for [*rows*](#glossary:row) in a given *billing period* MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account). ## Column ID diff --git a/specification/columns/billingperiodstart.md b/specification/columns/billingperiodstart.md index bc54163c5..54b198c31 100644 --- a/specification/columns/billingperiodstart.md +++ b/specification/columns/billingperiodstart.md @@ -2,7 +2,7 @@ Billing Period Start represents the [*inclusive*](#glossary:inclusivebound) start date and time of a [*billing period*](#glossary:billing-period). For example, a time period where BillingPeriodStart is '2024-01-01T00:00:00Z' and [BillingPeriodEnd](#billingperiodend) is '2024-02-01T00:00:00Z' includes charges for January, since BillingPeriodStart is inclusive, but does not include charges for February since BillingPeriodEnd is [*exclusive*](#glossary:exclusivebound). -The BillingPeriodStart column MUST be present in a FOCUS dataset, MUST be of type [Date/Time Format](#date/timeformat), MUST be an *inclusive* value, and MUST NOT contain null values. The sum of the [BilledCost](#billedcost) metric for [*rows*](#glossary:row) in a given *billing period* MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account). +The BillingPeriodStart column MUST be present in a FOCUS dataset, MUST be of type [DateTimeFormat](#date/timeformat), MUST be an *inclusive* value, and MUST NOT contain null values. The sum of the [BilledCost](#billedcost) metric for [*rows*](#glossary:row) in a given *billing period* MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account). ## Column ID diff --git a/specification/columns/consumedquantity.md b/specification/columns/consumedquantity.md index b29caa225..c4ffb19a3 100644 --- a/specification/columns/consumedquantity.md +++ b/specification/columns/consumedquantity.md @@ -5,7 +5,7 @@ The Consumed Quantity represents the volume of a metered SKU associated with a [ The ConsumedQuantity column adheres to the following requirements: * ConsumedQuantity MUST be present in a FOCUS dataset when the provider supports the measurement of usage. -* ConsumedQuantity MUST be of type Decimal and MUST conform to [Numeric Format](#numericformat) requirements. +* ConsumedQuantity MUST be of type Decimal and MUST conform to [NumericFormat](#numericformat) requirements. * ConsumedQuantity MUST NOT be null and MUST be a valid positive decimal value if [ChargeCategory](#chargecategory) is "Usage", [CommitmentDiscountStatus](#commitmentdiscountstatus) is not "Unused", and [ChargeClass](#chargeclass) is not "Correction". * ConsumedQuantity MAY be null or any valid decimal value if ChargeCategory is "Usage", CommitmentDiscountStatus is not "Unused", and ChargeClass is "Correction". * ConsumedQuantity MUST be null in all other cases. diff --git a/specification/columns/contractedcost.md b/specification/columns/contractedcost.md index 2c15aac25..8dda88594 100644 --- a/specification/columns/contractedcost.md +++ b/specification/columns/contractedcost.md @@ -2,7 +2,7 @@ Contracted Cost represents the cost calculated by multiplying [*contracted unit price*](#glossary:contracted-unit-price) and the corresponding [Pricing Quantity](#pricingquantity). Contracted Cost is denominated in the [Billing Currency](#billingcurrency) and is commonly used for calculating savings based on negotiation activities, by comparing it with [List Cost](#listcost). If [*negotiated discounts*](#glossary:negotiated-discount) are not applicable, the Contracted Cost defaults to the List Cost. -The ContractedCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. When [ContractedUnitPrice](#contractedunitprice) is present and not null, multiplying the ContractedUnitPrice by PricingQuantity MUST produce the ContractedCost, except in cases of [ChargeClass](#chargeclass) "Correction", which may address PricingQuantity or any cost discrepancies independently. +The ContractedCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [NumericFormat](#numericformat) requirements, and be denominated in the BillingCurrency. When [ContractedUnitPrice](#contractedunitprice) is present and not null, multiplying the ContractedUnitPrice by PricingQuantity MUST produce the ContractedCost, except in cases of [ChargeClass](#chargeclass) "Correction", which may address PricingQuantity or any cost discrepancies independently. In cases where the ContractedUnitPrice is present and null, the following applies: diff --git a/specification/columns/contractedunitprice.md b/specification/columns/contractedunitprice.md index d0deec909..796f84842 100644 --- a/specification/columns/contractedunitprice.md +++ b/specification/columns/contractedunitprice.md @@ -2,7 +2,7 @@ The Contracted Unit Price represents the agreed-upon unit price for a single [Pricing Unit](#pricingunit) of the associated SKU, inclusive of [*negotiated discounts*](#glossary:negotiated-discount), if present, while excluding negotiated [*commitment discounts*](#glossary:commitment-discount) or any other discounts. This price is denominated in the [Billing Currency](#billingcurrency). The Contracted Unit Price is commonly used for calculating savings based on negotiation activities. If negotiated discounts are not applicable, the Contracted Unit Price defaults to the [List Unit Price](#listunitprice). -The ContractedUnitPrice column MUST be present in a FOCUS dataset when the provider supports negotiated pricing concepts. This column MUST be a Decimal within the range of non-negative decimal values, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When ContractedUnitPrice is present and not null, multiplying ContractedUnitPrice by [PricingQuantity](#pricingquantity) MUST equal [ContractedCost](#contractedcost), except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. +The ContractedUnitPrice column MUST be present in a FOCUS dataset when the provider supports negotiated pricing concepts. This column MUST be a Decimal within the range of non-negative decimal values, MUST conform to [NumericFormat](#numericformat) requirements, and be denominated in the BillingCurrency. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When ContractedUnitPrice is present and not null, multiplying ContractedUnitPrice by [PricingQuantity](#pricingquantity) MUST equal [ContractedCost](#contractedcost), except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. ## Column ID diff --git a/specification/columns/effectivecost.md b/specification/columns/effectivecost.md index 45424f4ff..d9758c1f6 100644 --- a/specification/columns/effectivecost.md +++ b/specification/columns/effectivecost.md @@ -7,7 +7,7 @@ This column resolves two challenges that are faced by practitioners: 1. Practitioners need to *amortize* relevant purchases, such as upfront fees, throughout the *commitment* and distribute them to the appropriate reporting groups (e.g. [*tags*](#glossary:tag), [*resources*](#glossary:resource)). 2. Many [*commitment discount*](#glossary:commitment-discount) constructs include a recurring expense for the *commitment* for every [*billing period*](#glossary:billing-period) and must distribute this cost to the *resources* using the *commitment*. This forces reconciliation between the initial *commitment* [*row*](#glossary:row) per period and the actual usage *rows*. -The EffectiveCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. EffectiveCost MUST be 0 when ChargeCategory is "Purchase" and the purchase is intended to cover future eligible charges. The aggregated EffectiveCost for a billing period may not match the charge received on the invoice for the same *billing period*. +The EffectiveCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [NumericFormat](#numericformat) requirements, and be denominated in the BillingCurrency. EffectiveCost MUST be 0 when ChargeCategory is "Purchase" and the purchase is intended to cover future eligible charges. The aggregated EffectiveCost for a billing period may not match the charge received on the invoice for the same *billing period*. In cases where the [ChargeCategory](#chargecategory) is not "Usage" or "Purchase", the following applies: diff --git a/specification/columns/listcost.md b/specification/columns/listcost.md index cb0e69877..ce644df93 100644 --- a/specification/columns/listcost.md +++ b/specification/columns/listcost.md @@ -2,7 +2,7 @@ List Cost represents the cost calculated by multiplying the [*list unit price*](#glossary:list-unit-price) and the corresponding [Pricing Quantity](#pricingquantity). List Cost is denominated in the [Billing Currency](#billingcurrency) and is commonly used for calculating savings based on various rate optimization activities, by comparing it with [Contracted Cost](#contractedcost), [Billed Cost](#billedcost) and [Effective Cost](#effectivecost). -The ListCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. When [ListUnitPrice](#listunitprice) is present and not null, multiplying the ListUnitPrice by PricingQuantity MUST produce the ListCost, except in cases of [ChargeClass](#chargeclass) "Correction", which may address PricingQuantity or any cost discrepancies independently. +The ListCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [NumericFormat](#numericformat) requirements, and be denominated in the BillingCurrency. When [ListUnitPrice](#listunitprice) is present and not null, multiplying the ListUnitPrice by PricingQuantity MUST produce the ListCost, except in cases of [ChargeClass](#chargeclass) "Correction", which may address PricingQuantity or any cost discrepancies independently. In cases where the ListUnitPrice is present and is null, the following applies: diff --git a/specification/columns/listunitprice.md b/specification/columns/listunitprice.md index c014b2382..86ffd1d78 100644 --- a/specification/columns/listunitprice.md +++ b/specification/columns/listunitprice.md @@ -2,7 +2,7 @@ The List Unit Price represents the suggested provider-published unit price for a single [Pricing Unit](#pricingunit) of the associated SKU, exclusive of any discounts. This price is denominated in the [Billing Currency](#billingcurrency). The List Unit Price is commonly used for calculating savings based on various rate optimization activities. -The ListUnitPrice column MUST be present in a FOCUS dataset when the provider publishes unit prices exclusive of discounts. This column MUST be a Decimal within the range of non-negative decimal values, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When ListUnitPrice is present and is not null, multiplying ListUnitPrice by [PricingQuantity](#pricingquantity) MUST equal [ListCost](#listcost), except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. +The ListUnitPrice column MUST be present in a FOCUS dataset when the provider publishes unit prices exclusive of discounts. This column MUST be a Decimal within the range of non-negative decimal values, MUST conform to [NumericFormat](#numericformat) requirements, and be denominated in the BillingCurrency. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When ListUnitPrice is present and is not null, multiplying ListUnitPrice by [PricingQuantity](#pricingquantity) MUST equal [ListCost](#listcost), except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. ## Column ID diff --git a/specification/columns/pricingquantity.md b/specification/columns/pricingquantity.md index b858443da..940a1d5be 100644 --- a/specification/columns/pricingquantity.md +++ b/specification/columns/pricingquantity.md @@ -2,7 +2,7 @@ The Pricing Quantity represents the volume of a given SKU associated with a [*resource*](#glossary:resource) or [*service*](#glossary:service) used or purchased, based on the [Pricing Unit](#pricingunit). Distinct from [Consumed Quantity](#consumedquantity) (complementary to [Consumed Unit](#consumedunit)), it focuses on pricing and cost, not *resource* and *service* consumption. -The PricingQuantity column MUST be present in a FOCUS dataset. This column MUST be of type Decimal and MUST conform to [Numeric Format](#numericformat) requirements. The value MAY be negative in cases where [ChargeClass](#chargeclass) is "Correction". This column MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When unit prices are not null, multiplying PricingQuantity by a unit price MUST produce a result equal to the corresponding cost metric, except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. +The PricingQuantity column MUST be present in a FOCUS dataset. This column MUST be of type Decimal and MUST conform to [NumericFormat](#numericformat) requirements. The value MAY be negative in cases where [ChargeClass](#chargeclass) is "Correction". This column MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When unit prices are not null, multiplying PricingQuantity by a unit price MUST produce a result equal to the corresponding cost metric, except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. ## Column ID diff --git a/specification/columns/tags.md b/specification/columns/tags.md index f97b75d92..4a9c8039e 100644 --- a/specification/columns/tags.md +++ b/specification/columns/tags.md @@ -9,7 +9,7 @@ The Tags column adheres to the following requirements: * The Tags column MUST be present in a FOCUS dataset when the provider supports setting user or provider-defined tags. * The Tags column MUST contain user-defined and provider-defined tags. * The Tags column MUST only contain finalized tags. -* The Tags column MUST be in [Key-Value Format](#key-valueformat). +* The Tags column MUST be in [KeyValueFormat](#key-valueformat). * A Tag key with a non-null value for a given resource SHOULD be included in the tags column. * A Tag key with a null value for a given resource MAY be included in the tags column depending on the provider's tag finalization process. * A Tag key that does *not* support a corresponding value, MUST have a corresponding true (boolean) value set. diff --git a/specification/metadata/schema/creationdate.md b/specification/metadata/schema/creationdate.md index 77cbc92fd..2a1afc2bb 100644 --- a/specification/metadata/schema/creationdate.md +++ b/specification/metadata/schema/creationdate.md @@ -2,7 +2,7 @@ Date the schema was created. -The CreationDate MUST be present in the metadata. This MUST be of type Date/Time and MUST NOT contain null values. CreationDate MUST conform to [Date/Time Format](#date/timeformat). +The CreationDate MUST be present in the metadata. This MUST be of type Date/Time and MUST NOT contain null values. CreationDate MUST conform to [DateTimeFormat](#date/timeformat). ## Metadata ID From c6fb404623857192dbfb726d63d6debcbcad1a64 Mon Sep 17 00:00:00 2001 From: Irena Jurica Date: Wed, 9 Oct 2024 01:15:32 +0200 Subject: [PATCH 51/52] Editorial changes - links to FOCUS dataset glossary term (#592) Editorial changes: - Replaced ...MUST be present in the billing data... with ...MUST be present in a **[*FOCUS dataset*](#glossary:FOCUS-dataset)**... in the following columns: - CapacityReservation - ChargeClass - ConsumedUnit - SkuMeter - Added **links to the FOCUS dataset glossary term** for the remaining columns and other instances where the FOCUS dataset is mentioned. --- **Note:** For three columns, there are concurrent editorial PRs addressing column ID formatting and making changes to the same code line. To simplify the merge process and avoid conflicts, **links to the FOCUS dataset term** are not included in this PR but have been **added as suggestions in the respective PRs**: - SKU Price Details (see PR #588) - SKU Price ID (see PR #588) - Pricing Unit (see PR #589) --------- Co-authored-by: Joaquin --- EDITORIAL_GUIDELINES.md | 2 +- .../examples/metadata_examples/metadata_examples.mdpp | 2 +- .../metadata_examples/provider_version_changed_example.md | 2 +- specification/attributes/attributes.mdpp | 2 +- specification/attributes/column_naming_and_ordering.md | 2 +- specification/attributes/currency_code_format.md | 2 +- specification/attributes/datetime_format.md | 2 +- specification/attributes/key_value_format.md | 2 +- specification/attributes/numeric_format.md | 2 +- specification/attributes/string_handling.md | 2 +- specification/attributes/unit_format.md | 4 ++-- specification/columns/billedcost.md | 2 +- specification/columns/billingaccountid.md | 2 +- specification/columns/billingaccountname.md | 2 +- specification/columns/billingcurrency.md | 2 +- specification/columns/billingperiodend.md | 2 +- specification/columns/billingperiodstart.md | 2 +- specification/columns/capacityreservationid.md | 2 +- specification/columns/capacityreservationstatus.md | 2 +- specification/columns/chargecategory.md | 2 +- specification/columns/chargeclass.md | 2 +- specification/columns/chargedescription.md | 2 +- specification/columns/chargefrequency.md | 2 +- specification/columns/chargeperiodend.md | 2 +- specification/columns/chargeperiodstart.md | 2 +- specification/columns/commitmentdiscountcategory.md | 2 +- specification/columns/commitmentdiscountid.md | 2 +- specification/columns/commitmentdiscountname.md | 2 +- specification/columns/commitmentdiscountquantity.md | 6 +++--- specification/columns/commitmentdiscountstatus.md | 2 +- specification/columns/commitmentdiscounttype.md | 2 +- specification/columns/commitmentdiscountunit.md | 2 +- specification/columns/consumedquantity.md | 4 ++-- specification/columns/consumedunit.md | 2 +- specification/columns/contractedcost.md | 2 +- specification/columns/contractedunitprice.md | 2 +- specification/columns/effectivecost.md | 2 +- specification/columns/invoiceissuer.md | 2 +- specification/columns/listcost.md | 2 +- specification/columns/listunitprice.md | 2 +- specification/columns/pricingcategory.md | 2 +- specification/columns/pricingquantity.md | 2 +- specification/columns/provider.md | 2 +- specification/columns/publisher.md | 2 +- specification/columns/regionid.md | 2 +- specification/columns/regionname.md | 2 +- specification/columns/resourceid.md | 2 +- specification/columns/resourcename.md | 2 +- specification/columns/resourcetype.md | 2 +- specification/columns/servicecategory.md | 2 +- specification/columns/servicename.md | 2 +- specification/columns/servicesubcategory.md | 2 +- specification/columns/skuid.md | 2 +- specification/columns/skumeter.md | 4 ++-- specification/columns/subaccountid.md | 2 +- specification/columns/subaccountname.md | 2 +- specification/columns/tags.md | 2 +- specification/metadata/data_generator/datagenerator.md | 2 +- specification/metadata/metadata.mdpp | 2 +- .../schema/column_definition/column_definition.mdpp | 2 +- .../metadata/schema/column_definition/columnname.md | 2 +- specification/metadata/schema/column_definition/datatype.md | 2 +- .../schema/column_definition/providertagprefixes.md | 2 +- .../metadata/schema/column_definition/stringencoding.md | 2 +- specification/metadata/schema/focusversion.md | 2 +- specification/metadata/schema/providerversion.md | 2 +- specification/metadata/schema/schema.mdpp | 2 +- 67 files changed, 72 insertions(+), 72 deletions(-) diff --git a/EDITORIAL_GUIDELINES.md b/EDITORIAL_GUIDELINES.md index 189a612da..947acde16 100644 --- a/EDITORIAL_GUIDELINES.md +++ b/EDITORIAL_GUIDELINES.md @@ -136,7 +136,7 @@ These guidelines can be modified through a Pull Request (PR), which the members > > The **[Pricing Quantity](#pricing-quantity)** represents the volume of a given [SKU](#glossary:sku) associated with a [resource](#glossary:resource) or [service](#glossary:service) used or purchased, based on the **[Pricing Unit](#pricing-unit)**. Distinct from **[Consumed Quantity](#consumed-quantity)** (complementary to **[Consumed Unit](#consumed-unit)**), it focuses on pricing and cost, not resource and service consumption. > -> * The PricingQuantity column MUST be present in the billing data. +> * The PricingQuantity column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset). > * This column MUST be of type Decimal and MUST conform to Numeric Format requirements. > * The value MAY be negative in cases where ChargeClass is "Correction". > diff --git a/specification/appendix/examples/metadata_examples/metadata_examples.mdpp b/specification/appendix/examples/metadata_examples/metadata_examples.mdpp index eae6ee5f2..971e1df8b 100644 --- a/specification/appendix/examples/metadata_examples/metadata_examples.mdpp +++ b/specification/appendix/examples/metadata_examples/metadata_examples.mdpp @@ -1,6 +1,6 @@ # Metadata Examples -The following sections contain examples of metadata provided by a hypothetical FOCUS data provider called ACME to supply the required reference between the FOCUS dataset and the schema metadata. Provider implementations will vary on how the metadata is disseminated; however, the provider's chosen metadata delivery approach should be able to support the structure represented in this example. +The following sections contain examples of metadata provided by a hypothetical FOCUS data provider called ACME to supply the required reference between the [*FOCUS dataset*](#glossary:FOCUS-dataset) and the schema metadata. Provider implementations will vary on how the metadata is disseminated; however, the provider's chosen metadata delivery approach should be able to support the structure represented in this example. In this example, the provider supports delivery of FOCUS data via file export to a data storage system. It uses JSON as the format for providing the metadata. The provider delivers data every 12 hours into a path structure described below: diff --git a/specification/appendix/examples/metadata_examples/provider_version_changed_example.md b/specification/appendix/examples/metadata_examples/provider_version_changed_example.md index ed912bacf..3284c5eed 100644 --- a/specification/appendix/examples/metadata_examples/provider_version_changed_example.md +++ b/specification/appendix/examples/metadata_examples/provider_version_changed_example.md @@ -2,7 +2,7 @@ ## Scenario -ACME specifies the optional metadata property [Provider Version](#providerversion) in their [Schema](#schema) object. They made a change to the FOCUS dataset they produce that does not adopt a new FOCUS Version, nor make a change the included columns but does impact values in the data. This example illustrates that Provider Version changes are independent of column changes, however provider version changes may include column changes. +ACME specifies the optional metadata property [Provider Version](#providerversion) in their [Schema](#schema) object. They made a change to the [*FOCUS dataset*](#glossary:FOCUS-dataset) they produce that does not adopt a new FOCUS Version, nor make a change the included columns but does impact values in the data. This example illustrates that Provider Version changes are independent of column changes, however provider version changes may include column changes. The provider creates a new schema object to represent the new schema. The provider includes both the FOCUS Version and Provider Version in the schema object. diff --git a/specification/attributes/attributes.mdpp b/specification/attributes/attributes.mdpp index 36fe447e9..595ceebba 100644 --- a/specification/attributes/attributes.mdpp +++ b/specification/attributes/attributes.mdpp @@ -1,6 +1,6 @@ # Attributes -Attributes are requirements that apply across a FOCUS dataset instead of an individual column level. Requirements on data content can include naming +Attributes are requirements that apply across a [*FOCUS dataset*](#glossary:FOCUS-dataset) instead of an individual column level. Requirements on data content can include naming conventions, data types, formatting standardizations, etc. Attributes may introduce high-level requirements for data granularity, recency, frequency, etc. Requirements defined in attributes are necessary for servicing [FinOps capabilities][FODOFC] accurately using a standard set of instructions regardless of the origin of the data. diff --git a/specification/attributes/column_naming_and_ordering.md b/specification/attributes/column_naming_and_ordering.md index d21360e03..410c61894 100644 --- a/specification/attributes/column_naming_and_ordering.md +++ b/specification/attributes/column_naming_and_ordering.md @@ -14,7 +14,7 @@ Column Naming and Ordering ## Description -Naming and ordering convention for columns appearing in a FOCUS dataset. +Naming and ordering convention for columns appearing in a [*FOCUS dataset*](#glossary:FOCUS-dataset). ## Requirements diff --git a/specification/attributes/currency_code_format.md b/specification/attributes/currency_code_format.md index 68c5b2a68..a0f53f449 100644 --- a/specification/attributes/currency_code_format.md +++ b/specification/attributes/currency_code_format.md @@ -14,7 +14,7 @@ Currency Code Format ## Description -Formatting for currency columns appearing in a FOCUS dataset. +Formatting for currency columns appearing in a [*FOCUS dataset*](#glossary:FOCUS-dataset). ## Requirements diff --git a/specification/attributes/datetime_format.md b/specification/attributes/datetime_format.md index d04b6e032..b6b013df7 100644 --- a/specification/attributes/datetime_format.md +++ b/specification/attributes/datetime_format.md @@ -14,7 +14,7 @@ Date/Time Format ## Description -Rules and formatting requirements for date/time-related columns appearing in a FOCUS dataset. +Rules and formatting requirements for date/time-related columns appearing in a [*FOCUS dataset*](#glossary:FOCUS-dataset). ## Requirements diff --git a/specification/attributes/key_value_format.md b/specification/attributes/key_value_format.md index 136d81447..9ae056915 100644 --- a/specification/attributes/key_value_format.md +++ b/specification/attributes/key_value_format.md @@ -14,7 +14,7 @@ Key-Value Format ## Description -Rules and formatting requirements for columns appearing in a FOCUS dataset that convey data as key-value pairs. +Rules and formatting requirements for columns appearing in a [*FOCUS dataset*](#glossary:FOCUS-dataset) that convey data as key-value pairs. ## Requirements diff --git a/specification/attributes/numeric_format.md b/specification/attributes/numeric_format.md index 992a60c56..cf9980562 100644 --- a/specification/attributes/numeric_format.md +++ b/specification/attributes/numeric_format.md @@ -14,7 +14,7 @@ Numeric Format ## Description -Rules and formatting requirements for numeric columns appearing in a FOCUS dataset. +Rules and formatting requirements for numeric columns appearing in a [*FOCUS dataset*](#glossary:FOCUS-dataset). ## Requirements diff --git a/specification/attributes/string_handling.md b/specification/attributes/string_handling.md index 108fb8f08..7beb1e014 100644 --- a/specification/attributes/string_handling.md +++ b/specification/attributes/string_handling.md @@ -14,7 +14,7 @@ String Handling ## Description -Requirements for string-capturing columns appearing in a FOCUS dataset. +Requirements for string-capturing columns appearing in a [*FOCUS dataset*](#glossary:FOCUS-dataset). ## Requirements diff --git a/specification/attributes/unit_format.md b/specification/attributes/unit_format.md index 7fa10a32c..929dc9cbb 100644 --- a/specification/attributes/unit_format.md +++ b/specification/attributes/unit_format.md @@ -1,6 +1,6 @@ # Unit Format -Billing data frequently captures data measured in units related to data size, count, time, and other [*dimensions*](#glossary:dimension). The Unit Format attribute provides a standard for expressing units of measure in columns appearing in a FOCUS dataset. +Billing data frequently captures data measured in units related to data size, count, time, and other [*dimensions*](#glossary:dimension). The Unit Format attribute provides a standard for expressing units of measure in columns appearing in a [*FOCUS dataset*](#glossary:FOCUS-dataset). All columns defined in FOCUS specifying Unit Format as a value format MUST follow the requirements listed below. @@ -14,7 +14,7 @@ Unit Format ## Description -Indicates standards for expressing measurement units in columns appearing in a FOCUS dataset. +Indicates standards for expressing measurement units in columns appearing in a *FOCUS dataset*. ## Requirements diff --git a/specification/columns/billedcost.md b/specification/columns/billedcost.md index 5daaa0285..eb54c5ec3 100644 --- a/specification/columns/billedcost.md +++ b/specification/columns/billedcost.md @@ -2,7 +2,7 @@ The [*billed cost*](#glossary:billed-cost) represents a charge serving as the basis for invoicing, inclusive of the impacts of all reduced rates and discounts while excluding the [*amortization*](#glossary:amortization) of relevant purchases (one-time or recurring) paid to cover future eligible charges. This cost is denominated in the [Billing Currency](#billingcurrency). The Billed Cost is commonly used to perform FinOps capabilities that require cash-basis accounting such as cost allocation, budgeting, and invoice reconciliation. -The BilledCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [NumericFormat](#numericformat), and be denominated in the BillingCurrency. The sum of the BilledCost for [*rows*](#glossary:row) in a given [*billing period*](#glossary:billing-period) MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account). +The BilledCost column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat), and be denominated in the BillingCurrency. The sum of the BilledCost for [*rows*](#glossary:row) in a given [*billing period*](#glossary:billing-period) MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account). ## Column ID diff --git a/specification/columns/billingaccountid.md b/specification/columns/billingaccountid.md index e2b3a1a74..b66ccd0e0 100644 --- a/specification/columns/billingaccountid.md +++ b/specification/columns/billingaccountid.md @@ -2,7 +2,7 @@ A Billing Account ID is a provider-assigned identifier for a [*billing account*](#glossary:billing-account). *Billing accounts* are commonly used for scenarios like grouping based on organizational constructs, invoice reconciliation and cost allocation strategies. -The BillingAccountId column MUST be present in a FOCUS dataset. This column MUST be of type String and MUST NOT contain null values. BillingAccountId MUST be a globally unique identifier within a provider. +The BillingAccountId column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset). This column MUST be of type String and MUST NOT contain null values. BillingAccountId MUST be a globally unique identifier within a provider. See [Appendix: Grouping constructs for resources or services](#groupingconstructsforresourcesorservices) for details and examples of the different grouping constructs supported by FOCUS. diff --git a/specification/columns/billingaccountname.md b/specification/columns/billingaccountname.md index b5ced23e6..cdfb8fe9b 100644 --- a/specification/columns/billingaccountname.md +++ b/specification/columns/billingaccountname.md @@ -2,7 +2,7 @@ A Billing Account Name is a display name assigned to a [*billing account*](#glossary:billing-account). *Billing accounts* are commonly used for scenarios like grouping based on organizational constructs, invoice reconciliation and cost allocation strategies. -The BillingAccountName column MUST be present in a FOCUS dataset and MUST NOT be null when the provider supports assigning a display name for the *billing account*. This column MUST be of type String. BillingAccountName MUST be unique within a customer when a customer has more than one *billing account*. +The BillingAccountName column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) and MUST NOT be null when the provider supports assigning a display name for the *billing account*. This column MUST be of type String. BillingAccountName MUST be unique within a customer when a customer has more than one *billing account*. See [Appendix: Grouping constructs for resources or services](#groupingconstructsforresourcesorservices) for details and examples of the different grouping constructs supported by FOCUS. diff --git a/specification/columns/billingcurrency.md b/specification/columns/billingcurrency.md index e60e127de..8dfd03818 100644 --- a/specification/columns/billingcurrency.md +++ b/specification/columns/billingcurrency.md @@ -2,7 +2,7 @@ [*Billing currency*](#glossary:billing-currency) is an identifier that represents the currency that a charge for [*resources*](#glossary:resource) or [*services*](#glossary:service) was billed in. Billing Currency is commonly used in scenarios where costs need to be grouped or aggregated. -The BillingCurrency column MUST be present in a FOCUS dataset. BillingCurrency MUST match the currency used in the invoice generated by the invoice issuer. This column MUST be of type String and MUST NOT contain null values. BillingCurrency MUST conform to [CurrencyCodeFormat](#currencycodeformat) requirements. +The BillingCurrency column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset). BillingCurrency MUST match the currency used in the invoice generated by the invoice issuer. This column MUST be of type String and MUST NOT contain null values. BillingCurrency MUST conform to [Currency Code Format](#currencycodeformat) requirements. ## Column ID diff --git a/specification/columns/billingperiodend.md b/specification/columns/billingperiodend.md index fcd2cbaf2..f0303f384 100644 --- a/specification/columns/billingperiodend.md +++ b/specification/columns/billingperiodend.md @@ -2,7 +2,7 @@ Billing Period End represents the [*exclusive*](#glossary:exclusivebound) end date and time of a [*billing period*](#glossary:billing-period). For example, a time period where [BillingPeriodStart](#glossary:billingperiodstart) is '2024-01-01T00:00:00Z' and BillingPeriodEnd is '2024-02-01T00:00:00Z' includes charges for January, since BillingPeriodStart is [*inclusive*](#glossary:inclusivebound), but does not include charges for February since BillingPeriodEnd is *exclusive*. -The BillingPeriodEnd column MUST be present in a FOCUS dataset. This column MUST be of type [DateTimeFormat](#date/timeformat), MUST be an *exclusive* value, and MUST NOT contain null values. The sum of the [BilledCost](#billedcost) column for [*rows*](#glossary:row) in a given *billing period* MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account). +The BillingPeriodEnd column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset). This column MUST be of type [Date/Time Format](#date/timeformat), MUST be an *exclusive* value, and MUST NOT contain null values. The sum of the [BilledCost](#billedcost) column for [*rows*](#glossary:row) in a given *billing period* MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account). ## Column ID diff --git a/specification/columns/billingperiodstart.md b/specification/columns/billingperiodstart.md index 54b198c31..9289a10ea 100644 --- a/specification/columns/billingperiodstart.md +++ b/specification/columns/billingperiodstart.md @@ -2,7 +2,7 @@ Billing Period Start represents the [*inclusive*](#glossary:inclusivebound) start date and time of a [*billing period*](#glossary:billing-period). For example, a time period where BillingPeriodStart is '2024-01-01T00:00:00Z' and [BillingPeriodEnd](#billingperiodend) is '2024-02-01T00:00:00Z' includes charges for January, since BillingPeriodStart is inclusive, but does not include charges for February since BillingPeriodEnd is [*exclusive*](#glossary:exclusivebound). -The BillingPeriodStart column MUST be present in a FOCUS dataset, MUST be of type [DateTimeFormat](#date/timeformat), MUST be an *inclusive* value, and MUST NOT contain null values. The sum of the [BilledCost](#billedcost) metric for [*rows*](#glossary:row) in a given *billing period* MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account). +The BillingPeriodStart column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset), MUST be of type [Date/Time Format](#date/timeformat), MUST be an *inclusive* value, and MUST NOT contain null values. The sum of the [BilledCost](#billedcost) metric for [*rows*](#glossary:row) in a given *billing period* MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account). ## Column ID diff --git a/specification/columns/capacityreservationid.md b/specification/columns/capacityreservationid.md index ddc836936..bd87afd80 100644 --- a/specification/columns/capacityreservationid.md +++ b/specification/columns/capacityreservationid.md @@ -4,7 +4,7 @@ A Capacity Reservation ID is the identifier assigned to a [*capacity reservation The CapacityReservationId column adheres to the following requirements: -* CapacityReservationId MUST be present in the billing data when the provider supports *capacity reservations* and MUST be of type String. +* CapacityReservationId MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports *capacity reservations* and MUST be of type String. * CapacityReservationId SHOULD NOT be null when a charge is related to a capacity reservation. * CapacityReservationId MUST NOT be null when a charge represents the unused portion of a *capacity reservation*. * CapacityReservationId MUST be null when a charge is not related to a *capacity reservation*. diff --git a/specification/columns/capacityreservationstatus.md b/specification/columns/capacityreservationstatus.md index 24b449c29..afc139b2e 100644 --- a/specification/columns/capacityreservationstatus.md +++ b/specification/columns/capacityreservationstatus.md @@ -4,7 +4,7 @@ Capacity Reservation Status indicates whether the charge represents either the c The CapacityReservationStatus column adheres to the following requirements: -* CapacityReservationStatus MUST be present in a FOCUS dataset when the provider supports *capacity reservations* and MUST be of type String. +* CapacityReservationStatus MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports *capacity reservations* and MUST be of type String. * CapacityReservationStatus MUST be null when CapacityReservationId is null. * CapacityReservationStatus MUST NOT be null when CapacityReservationId is not null and [ChargeCategory](#chargecategory) is "Usage". * CapacityReservationStatus MUST be one of the allowed values. diff --git a/specification/columns/chargecategory.md b/specification/columns/chargecategory.md index 41f183c26..e3e672ad9 100644 --- a/specification/columns/chargecategory.md +++ b/specification/columns/chargecategory.md @@ -2,7 +2,7 @@ Charge Category represents the highest-level classification of a charge based on the nature of how it is billed. Charge Category is commonly used to identify and distinguish between types of charges that may require different handling. -The ChargeCategory column MUST be present in a FOCUS dataset and MUST NOT be null. This column is of type String and MUST be one of the allowed values. +The ChargeCategory column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) and MUST NOT be null. This column is of type String and MUST be one of the allowed values. ## Column ID diff --git a/specification/columns/chargeclass.md b/specification/columns/chargeclass.md index 41866810e..85569d6aa 100644 --- a/specification/columns/chargeclass.md +++ b/specification/columns/chargeclass.md @@ -2,7 +2,7 @@ Charge Class indicates whether the row represents a correction to a previously invoiced [*billing period*](#glossary:billing-period). Charge Class is commonly used to differentiate corrections from regularly incurred charges. -The ChargeClass column MUST be present in the FOCUS dataset. This column MUST be of type String and MUST be "Correction" when the row represents a correction to a previously invoiced *billing period*. ChargeClass MUST be null when it is not a correction or when it is a correction within the current *billing period*. +The ChargeClass column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset). This column MUST be of type String and MUST be "Correction" when the row represents a correction to a previously invoiced *billing period*. ChargeClass MUST be null when it is not a correction or when it is a correction within the current *billing period*. ## Column ID diff --git a/specification/columns/chargedescription.md b/specification/columns/chargedescription.md index 0f875c6e4..e0b280f2e 100644 --- a/specification/columns/chargedescription.md +++ b/specification/columns/chargedescription.md @@ -2,7 +2,7 @@ A Charge Description provides a high-level context of a [*row*](#glossary:row) without requiring additional discovery. This column is a self-contained summary of the charge's purpose and price. It typically covers a select group of corresponding details across a billing dataset or provides information not otherwise available. -The ChargeDescription column MUST be present in a FOCUS dataset, MUST be of type String, and SHOULD NOT be null. Providers SHOULD specify the length of this column in their publicly available documentation. +The ChargeDescription column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset), MUST be of type String, and SHOULD NOT be null. Providers SHOULD specify the length of this column in their publicly available documentation. ## Column ID diff --git a/specification/columns/chargefrequency.md b/specification/columns/chargefrequency.md index 45d94183c..3f5c1d825 100644 --- a/specification/columns/chargefrequency.md +++ b/specification/columns/chargefrequency.md @@ -2,7 +2,7 @@ Charge Frequency indicates how often a charge will occur. Along with the [charge period](#glossary:chargeperiod) related columns, the Charge Frequency is commonly used to understand recurrence periods (e.g., monthly, yearly), forecast upcoming charges, and differentiate between one-time and recurring fees for purchases. -The ChargeFrequency column is RECOMMENDED be present in a FOCUS dataset and MUST NOT be null. This column is of type String and MUST be one of the allowed values. When [ChargeCategory](#chargecategory) is "Purchase", ChargeFrequency MUST NOT be "Usage-Based". +The ChargeFrequency column is RECOMMENDED be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) and MUST NOT be null. This column is of type String and MUST be one of the allowed values. When [ChargeCategory](#chargecategory) is "Purchase", ChargeFrequency MUST NOT be "Usage-Based". ## Column ID diff --git a/specification/columns/chargeperiodend.md b/specification/columns/chargeperiodend.md index c7e5060e8..d0eccd134 100644 --- a/specification/columns/chargeperiodend.md +++ b/specification/columns/chargeperiodend.md @@ -2,7 +2,7 @@ Charge Period End represents the [*exclusive*](#glossary:exclusivebound) end date and time of a [*charge period*](#glossary:chargeperiod). For example, a time period where [ChargePeriodStart](#chargeperiodstart) is '2024-01-01T00:00:00Z' and ChargePeriodEnd is '2024-01-02T00:00:00Z' includes charges for January 1, since ChargePeriodStart is [*inclusive*](#glossary:inclusivebound), but does not include charges for January 2 since ChargePeriodEnd is *exclusive*. -ChargePeriodEnd MUST be present in a FOCUS dataset, MUST be of type Date/Time, MUST be an *exclusive* value, and MUST NOT contain null values. ChargePeriodEnd MUST match the ending date and time boundary of the effective period of the charge. +ChargePeriodEnd MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset), MUST be of type Date/Time, MUST be an *exclusive* value, and MUST NOT contain null values. ChargePeriodEnd MUST match the ending date and time boundary of the effective period of the charge. ## Column ID diff --git a/specification/columns/chargeperiodstart.md b/specification/columns/chargeperiodstart.md index fe701b161..2d4d4700a 100644 --- a/specification/columns/chargeperiodstart.md +++ b/specification/columns/chargeperiodstart.md @@ -2,7 +2,7 @@ Charge Period Start represents the [*inclusive*](#glossary:inclusivebound) start date and time within a [*charge period*](#glossary:chargeperiod). For example, a time period where ChargePeriodStart is '2024-01-01T00:00:00Z' and [ChargePeriodEnd](#chargeperiodend) is '2024-01-02T00:00:00Z' includes charges for January 1, since ChargePeriodStart is *inclusive*, but does not include charges for January 2 since ChargePeriodEnd is [*exclusive*](#glossary:exclusivebound). -ChargePeriodStart MUST be present in a FOCUS dataset, MUST be of type Date/Time, MUST be an *inclusive* value, and MUST NOT contain null values. ChargePeriodStart MUST match the beginning date and time boundary of the effective period of the charge. +ChargePeriodStart MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset), MUST be of type Date/Time, MUST be an *inclusive* value, and MUST NOT contain null values. ChargePeriodStart MUST match the beginning date and time boundary of the effective period of the charge. ## Column ID diff --git a/specification/columns/commitmentdiscountcategory.md b/specification/columns/commitmentdiscountcategory.md index 357642cfc..44c111b02 100644 --- a/specification/columns/commitmentdiscountcategory.md +++ b/specification/columns/commitmentdiscountcategory.md @@ -2,7 +2,7 @@ Commitment Discount Category indicates whether the [*commitment discount*](#glossary:commitment-discount) identified in the CommitmentDiscountId column is based on usage quantity or cost (aka "spend"). The CommitmentDiscountCategory column is only applicable to *commitment discounts* and not [*negotiated discounts*](#glossary:negotiated-discount). -The CommitmentDiscountCategory column MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. This column MUST be of type String, MUST be null when [CommitmentDiscountId](#commitmentdiscountid) is null, and MUST NOT be null when CommitmentDiscountId is not null. The CommitmentDiscountCategory MUST be one of the allowed values. +The CommitmentDiscountCategory column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports *commitment discounts*. This column MUST be of type String, MUST be null when [CommitmentDiscountId](#commitmentdiscountid) is null, and MUST NOT be null when CommitmentDiscountId is not null. The CommitmentDiscountCategory MUST be one of the allowed values. ## Column ID diff --git a/specification/columns/commitmentdiscountid.md b/specification/columns/commitmentdiscountid.md index 94eb9d435..958b13744 100644 --- a/specification/columns/commitmentdiscountid.md +++ b/specification/columns/commitmentdiscountid.md @@ -2,7 +2,7 @@ A Commitment Discount ID is the identifier assigned to a [*commitment discount*](#glossary:commitment-discount) by the provider. Commitment Discount ID is commonly used for scenarios like chargeback for *commitments* and savings per *commitment discount*. The CommitmentDiscountId column is only applicable to *commitment discounts* and not [*negotiated discounts*](#glossary:negotiated-discount). -The CommitmentDiscountId column MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. This column MUST be of type String and MUST NOT contain null values when a charge is related to a *commitment discount*. When a charge is not associated with a *commitment discount*, the column MUST be null. CommitmentDiscountId MUST ensure global uniqueness within the provider and SHOULD be a fully-qualified identifier. +The CommitmentDiscountId column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports *commitment discounts*. This column MUST be of type String and MUST NOT contain null values when a charge is related to a *commitment discount*. When a charge is not associated with a *commitment discount*, the column MUST be null. CommitmentDiscountId MUST ensure global uniqueness within the provider and SHOULD be a fully-qualified identifier. ## Column ID diff --git a/specification/columns/commitmentdiscountname.md b/specification/columns/commitmentdiscountname.md index 66c8b1a84..72d2907ec 100644 --- a/specification/columns/commitmentdiscountname.md +++ b/specification/columns/commitmentdiscountname.md @@ -2,7 +2,7 @@ A Commitment Discount Name is the display name assigned to a [*commitment discount*](#glossary:commitment-discount). The CommitmentDiscountName column is only applicable to *commitment discounts* and not [*negotiated discounts*](#glossary:negotiated-discount). -The CommitmentDiscountName column MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. This column MUST be of type String. The CommitmentDiscountName value MUST be null if the charge is not related to a *commitment discount* and MAY be null if a display name cannot be assigned to a *commitment discount*. CommitmentDiscountName MUST NOT be null if a display name can be assigned to a *commitment discount*. +The CommitmentDiscountName column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports *commitment discounts*. This column MUST be of type String. The CommitmentDiscountName value MUST be null if the charge is not related to a *commitment discount* and MAY be null if a display name cannot be assigned to a *commitment discount*. CommitmentDiscountName MUST NOT be null if a display name can be assigned to a *commitment discount*. ## Column ID diff --git a/specification/columns/commitmentdiscountquantity.md b/specification/columns/commitmentdiscountquantity.md index 464bc2dfe..650e2f50d 100644 --- a/specification/columns/commitmentdiscountquantity.md +++ b/specification/columns/commitmentdiscountquantity.md @@ -6,9 +6,9 @@ When [CommitmentDiscountCategory](#commitmentdiscountcategory) is "Usage" (usage The CommitmentDiscountQuantity column adheres to the following requirements: -* CommitmentDiscountQuantity MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. -* CommitmentDiscountQuantity MUST be of type Decimal and MUST conform to [NumericFormat](#numericformat) requirements. -* CommitmentDiscountQuantity MAY be null or any valid decimal value if [CommitmentDiscountId](#commitmentdiscountid) is not null and [ChargeClass](#chargeclass) is "Correction". +* CommitmentDiscountQuantity MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports *commitment discounts*. +* CommitmentDiscountQuantity MUST be of type Decimal and MUST conform to [Numeric Format](#numericformat) requirements. +* CommitmentDiscountQuantity MAY be null or any valid decimal value if [*CommitmentDiscountId*](#commitmentdiscountid) is not null and [*ChargeClass*](#chargeclass) is "Correction". In cases where the ChargeCategory is "Purchase", CommitmentDiscountId is not null, and ChargeClass is not "Correction", the following applies: diff --git a/specification/columns/commitmentdiscountstatus.md b/specification/columns/commitmentdiscountstatus.md index edc382186..2c5facecb 100644 --- a/specification/columns/commitmentdiscountstatus.md +++ b/specification/columns/commitmentdiscountstatus.md @@ -2,7 +2,7 @@ Commitment Discount Status indicates whether the charge corresponds with the consumption of a [*commitment discount*](#glossary:commitment-discount) identified in the CommitmentDiscountId column or the unused portion of the committed amount. The CommitmetnDiscountStatus column is only applicable to *commitment discounts* and not [*negotiated discounts*](#glossary:negotiated-discount). -The CommitmentDiscountStatus column MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. This column MUST be of type String, MUST be null when [CommitmentDiscountId](#commitmentdiscountid) is null, and MUST NOT be null when CommitmentDiscountId is not null and [Charge Category](#chargecategory) is "Usage". CommitmentDiscountStatus MUST be one of the allowed values. +The CommitmentDiscountStatus column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports *commitment discounts*. This column MUST be of type String, MUST be null when [CommitmentDiscountId](#commitmentdiscountid) is null, and MUST NOT be null when CommitmentDiscountId is not null and [Charge Category](#chargecategory) is "Usage". CommitmentDiscountStatus MUST be one of the allowed values. ## Column ID diff --git a/specification/columns/commitmentdiscounttype.md b/specification/columns/commitmentdiscounttype.md index 23cae2212..a88f1cf96 100644 --- a/specification/columns/commitmentdiscounttype.md +++ b/specification/columns/commitmentdiscounttype.md @@ -2,7 +2,7 @@ Commitment Discount Type is a provider-assigned name to identify the type of [*commitment discount*](#glossary:commitment-discount) applied to the [*row*](#glossary:row). The CommitmentDiscountType column is only applicable to *commitment discounts* and not [*negotiated discounts*](#glossary:negotiated-discount). -The CommitmentDiscountType column MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. This column MUST be of type String, MUST be null when [CommitmentDiscountId](#commitmentdiscountid) is null, and MUST NOT be null when CommitmentDiscountId is not null. +The CommitmentDiscountType column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports *commitment discounts*. This column MUST be of type String, MUST be null when [CommitmentDiscountId](#commitmentdiscountid) is null, and MUST NOT be null when CommitmentDiscountId is not null. ## Column ID diff --git a/specification/columns/commitmentdiscountunit.md b/specification/columns/commitmentdiscountunit.md index e64a03a5c..596f4df77 100644 --- a/specification/columns/commitmentdiscountunit.md +++ b/specification/columns/commitmentdiscountunit.md @@ -4,7 +4,7 @@ Commitment Discount Unit represents the provider-specified measurement unit indi The CommitmentDiscountUnit column adheres to the following requirements: -* CommitmentDiscountUnit MUST be present in a FOCUS dataset when the provider supports [*commitment discounts*](#glossary:commitment-discount). +* CommitmentDiscountUnit MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports [*commitment discounts*](#glossary:commitment-discount). * CommitmentDiscountUnit MUST be of type String, and the units of measure used in CommitmentDiscountUnit SHOULD adhere to the values and format requirements specified in the [UnitFormat](#unitformat) attribute. * The CommitmentDiscountUnit MUST be the same across all *rows* where CommitmentDiscountQuantity has the same [CommitmentDiscountId](#commitmentdiscountid). * CommitmentDiscountUnit MAY be null if CommitmentDiscountId is not null and [ChargeClass](#chargeclass) is "Correction". diff --git a/specification/columns/consumedquantity.md b/specification/columns/consumedquantity.md index c4ffb19a3..234f63b7e 100644 --- a/specification/columns/consumedquantity.md +++ b/specification/columns/consumedquantity.md @@ -4,8 +4,8 @@ The Consumed Quantity represents the volume of a metered SKU associated with a [ The ConsumedQuantity column adheres to the following requirements: -* ConsumedQuantity MUST be present in a FOCUS dataset when the provider supports the measurement of usage. -* ConsumedQuantity MUST be of type Decimal and MUST conform to [NumericFormat](#numericformat) requirements. +* ConsumedQuantity MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports the measurement of usage. +* ConsumedQuantity MUST be of type Decimal and MUST conform to [Numeric Format](#numericformat) requirements. * ConsumedQuantity MUST NOT be null and MUST be a valid positive decimal value if [ChargeCategory](#chargecategory) is "Usage", [CommitmentDiscountStatus](#commitmentdiscountstatus) is not "Unused", and [ChargeClass](#chargeclass) is not "Correction". * ConsumedQuantity MAY be null or any valid decimal value if ChargeCategory is "Usage", CommitmentDiscountStatus is not "Unused", and ChargeClass is "Correction". * ConsumedQuantity MUST be null in all other cases. diff --git a/specification/columns/consumedunit.md b/specification/columns/consumedunit.md index 36d2760f6..a9f7b78bc 100644 --- a/specification/columns/consumedunit.md +++ b/specification/columns/consumedunit.md @@ -4,7 +4,7 @@ The Consumed Unit represents a provider-specified measurement unit indicating ho The ConsumedUnit column adheres to the following requirements: -* ConsumedUnit MUST be present in the billing data when the provider supports the measurement of usage. +* ConsumedUnit MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports the measurement of usage. * ConsumedUnit MUST be of type String, and the units of measure used in ConsumedUnit SHOULD adhere to the values and format requirements specified in the [UnitFormat](#unitformat) attribute. * ConsumedUnit MUST NOT be null if [ChargeCategory](#chargecategory) is "Usage", [CommitmentDiscountStatus](#commitmentdiscountstatus) is not "Unused", and [ChargeClass](#chargeclass) is not "Correction". * ConsumedUnit MAY be null if ChargeCategory is "Usage", CommitmentDiscountStatus is not "Unused", and ChargeClass is "Correction". diff --git a/specification/columns/contractedcost.md b/specification/columns/contractedcost.md index 8dda88594..96a678312 100644 --- a/specification/columns/contractedcost.md +++ b/specification/columns/contractedcost.md @@ -2,7 +2,7 @@ Contracted Cost represents the cost calculated by multiplying [*contracted unit price*](#glossary:contracted-unit-price) and the corresponding [Pricing Quantity](#pricingquantity). Contracted Cost is denominated in the [Billing Currency](#billingcurrency) and is commonly used for calculating savings based on negotiation activities, by comparing it with [List Cost](#listcost). If [*negotiated discounts*](#glossary:negotiated-discount) are not applicable, the Contracted Cost defaults to the List Cost. -The ContractedCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [NumericFormat](#numericformat) requirements, and be denominated in the BillingCurrency. When [ContractedUnitPrice](#contractedunitprice) is present and not null, multiplying the ContractedUnitPrice by PricingQuantity MUST produce the ContractedCost, except in cases of [ChargeClass](#chargeclass) "Correction", which may address PricingQuantity or any cost discrepancies independently. +The ContractedCost column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. When [ContractedUnitPrice](#contractedunitprice) is present and not null, multiplying the ContractedUnitPrice by PricingQuantity MUST produce the ContractedCost, except in cases of [ChargeClass](#chargeclass) "Correction", which may address PricingQuantity or any cost discrepancies independently. In cases where the ContractedUnitPrice is present and null, the following applies: diff --git a/specification/columns/contractedunitprice.md b/specification/columns/contractedunitprice.md index 796f84842..36d21392b 100644 --- a/specification/columns/contractedunitprice.md +++ b/specification/columns/contractedunitprice.md @@ -2,7 +2,7 @@ The Contracted Unit Price represents the agreed-upon unit price for a single [Pricing Unit](#pricingunit) of the associated SKU, inclusive of [*negotiated discounts*](#glossary:negotiated-discount), if present, while excluding negotiated [*commitment discounts*](#glossary:commitment-discount) or any other discounts. This price is denominated in the [Billing Currency](#billingcurrency). The Contracted Unit Price is commonly used for calculating savings based on negotiation activities. If negotiated discounts are not applicable, the Contracted Unit Price defaults to the [List Unit Price](#listunitprice). -The ContractedUnitPrice column MUST be present in a FOCUS dataset when the provider supports negotiated pricing concepts. This column MUST be a Decimal within the range of non-negative decimal values, MUST conform to [NumericFormat](#numericformat) requirements, and be denominated in the BillingCurrency. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When ContractedUnitPrice is present and not null, multiplying ContractedUnitPrice by [PricingQuantity](#pricingquantity) MUST equal [ContractedCost](#contractedcost), except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. +The ContractedUnitPrice column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports negotiated pricing concepts. This column MUST be a Decimal within the range of non-negative decimal values, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When ContractedUnitPrice is present and not null, multiplying ContractedUnitPrice by [PricingQuantity](#pricingquantity) MUST equal [ContractedCost](#contractedcost), except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. ## Column ID diff --git a/specification/columns/effectivecost.md b/specification/columns/effectivecost.md index d9758c1f6..f54dec19d 100644 --- a/specification/columns/effectivecost.md +++ b/specification/columns/effectivecost.md @@ -7,7 +7,7 @@ This column resolves two challenges that are faced by practitioners: 1. Practitioners need to *amortize* relevant purchases, such as upfront fees, throughout the *commitment* and distribute them to the appropriate reporting groups (e.g. [*tags*](#glossary:tag), [*resources*](#glossary:resource)). 2. Many [*commitment discount*](#glossary:commitment-discount) constructs include a recurring expense for the *commitment* for every [*billing period*](#glossary:billing-period) and must distribute this cost to the *resources* using the *commitment*. This forces reconciliation between the initial *commitment* [*row*](#glossary:row) per period and the actual usage *rows*. -The EffectiveCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [NumericFormat](#numericformat) requirements, and be denominated in the BillingCurrency. EffectiveCost MUST be 0 when ChargeCategory is "Purchase" and the purchase is intended to cover future eligible charges. The aggregated EffectiveCost for a billing period may not match the charge received on the invoice for the same *billing period*. +The EffectiveCost column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. EffectiveCost MUST be 0 when ChargeCategory is "Purchase" and the purchase is intended to cover future eligible charges. The aggregated EffectiveCost for a billing period may not match the charge received on the invoice for the same *billing period*. In cases where the [ChargeCategory](#chargecategory) is not "Usage" or "Purchase", the following applies: diff --git a/specification/columns/invoiceissuer.md b/specification/columns/invoiceissuer.md index 7a1b76edf..dfe03ed11 100644 --- a/specification/columns/invoiceissuer.md +++ b/specification/columns/invoiceissuer.md @@ -3,7 +3,7 @@ An Invoice Issuer is an entity responsible for invoicing for the [*resources*](#glossary:resource) or [*services*](#glossary:service) consumed. It is commonly used for cost analysis and reporting scenarios. -The InvoiceIssuer column MUST be present in a FOCUS dataset. This column MUST be of type String and MUST NOT contain null values. +The InvoiceIssuer column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset). This column MUST be of type String and MUST NOT contain null values. See [Appendix: Origination of cost data](#originationofcostdata) section for examples of [Provider](#provider), [Publisher](#publisher) and Invoice Issuer values that can be used for various purchasing scenarios. diff --git a/specification/columns/listcost.md b/specification/columns/listcost.md index ce644df93..c2e6d3dd9 100644 --- a/specification/columns/listcost.md +++ b/specification/columns/listcost.md @@ -2,7 +2,7 @@ List Cost represents the cost calculated by multiplying the [*list unit price*](#glossary:list-unit-price) and the corresponding [Pricing Quantity](#pricingquantity). List Cost is denominated in the [Billing Currency](#billingcurrency) and is commonly used for calculating savings based on various rate optimization activities, by comparing it with [Contracted Cost](#contractedcost), [Billed Cost](#billedcost) and [Effective Cost](#effectivecost). -The ListCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [NumericFormat](#numericformat) requirements, and be denominated in the BillingCurrency. When [ListUnitPrice](#listunitprice) is present and not null, multiplying the ListUnitPrice by PricingQuantity MUST produce the ListCost, except in cases of [ChargeClass](#chargeclass) "Correction", which may address PricingQuantity or any cost discrepancies independently. +The ListCost column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. When [ListUnitPrice](#listunitprice) is present and not null, multiplying the ListUnitPrice by PricingQuantity MUST produce the ListCost, except in cases of [ChargeClass](#chargeclass) "Correction", which may address PricingQuantity or any cost discrepancies independently. In cases where the ListUnitPrice is present and is null, the following applies: diff --git a/specification/columns/listunitprice.md b/specification/columns/listunitprice.md index 86ffd1d78..d35d73b32 100644 --- a/specification/columns/listunitprice.md +++ b/specification/columns/listunitprice.md @@ -2,7 +2,7 @@ The List Unit Price represents the suggested provider-published unit price for a single [Pricing Unit](#pricingunit) of the associated SKU, exclusive of any discounts. This price is denominated in the [Billing Currency](#billingcurrency). The List Unit Price is commonly used for calculating savings based on various rate optimization activities. -The ListUnitPrice column MUST be present in a FOCUS dataset when the provider publishes unit prices exclusive of discounts. This column MUST be a Decimal within the range of non-negative decimal values, MUST conform to [NumericFormat](#numericformat) requirements, and be denominated in the BillingCurrency. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When ListUnitPrice is present and is not null, multiplying ListUnitPrice by [PricingQuantity](#pricingquantity) MUST equal [ListCost](#listcost), except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. +The ListUnitPrice column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider publishes unit prices exclusive of discounts. This column MUST be a Decimal within the range of non-negative decimal values, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When ListUnitPrice is present and is not null, multiplying ListUnitPrice by [PricingQuantity](#pricingquantity) MUST equal [ListCost](#listcost), except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. ## Column ID diff --git a/specification/columns/pricingcategory.md b/specification/columns/pricingcategory.md index ae0369498..504c807e9 100644 --- a/specification/columns/pricingcategory.md +++ b/specification/columns/pricingcategory.md @@ -4,7 +4,7 @@ Pricing Category describes the pricing model used for a charge at the time of us The PricingCategory column adheres to the following requirements: -* PricingCategory MUST be present in a FOCUS dataset when the provider supports more than one pricing category across all SKUs and MUST be of type String. +* PricingCategory MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports more than one pricing category across all SKUs and MUST be of type String. * PricingCategory MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. * PricingCategory MUST be one of the allowed values. * PricingCategory MUST be "Standard" when pricing is predetermined at the agreed upon rate for the [billing account](#glossary:billing-account). diff --git a/specification/columns/pricingquantity.md b/specification/columns/pricingquantity.md index 940a1d5be..2a10fb652 100644 --- a/specification/columns/pricingquantity.md +++ b/specification/columns/pricingquantity.md @@ -2,7 +2,7 @@ The Pricing Quantity represents the volume of a given SKU associated with a [*resource*](#glossary:resource) or [*service*](#glossary:service) used or purchased, based on the [Pricing Unit](#pricingunit). Distinct from [Consumed Quantity](#consumedquantity) (complementary to [Consumed Unit](#consumedunit)), it focuses on pricing and cost, not *resource* and *service* consumption. -The PricingQuantity column MUST be present in a FOCUS dataset. This column MUST be of type Decimal and MUST conform to [NumericFormat](#numericformat) requirements. The value MAY be negative in cases where [ChargeClass](#chargeclass) is "Correction". This column MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When unit prices are not null, multiplying PricingQuantity by a unit price MUST produce a result equal to the corresponding cost metric, except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. +The PricingQuantity column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset). This column MUST be of type Decimal and MUST conform to [Numeric Format](#numericformat) requirements. The value MAY be negative in cases where [ChargeClass](#chargeclass) is "Correction". This column MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When unit prices are not null, multiplying PricingQuantity by a unit price MUST produce a result equal to the corresponding cost metric, except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. ## Column ID diff --git a/specification/columns/provider.md b/specification/columns/provider.md index e17f43e90..a88b07b69 100644 --- a/specification/columns/provider.md +++ b/specification/columns/provider.md @@ -2,7 +2,7 @@ A Provider is an entity that makes the [*resources*](#glossary:resource) or [*services*](#glossary:service) available for purchase. It is commonly used for cost analysis and reporting scenarios. -The Provider column MUST be present in a FOCUS dataset. This column MUST be of type String and MUST NOT contain null values. +The Provider column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset). This column MUST be of type String and MUST NOT contain null values. See [Appendix: Origination of cost data](#originationofcostdata) section for examples of Provider, Publisher and Invoice Issuer values that can be used for various purchasing scenarios. diff --git a/specification/columns/publisher.md b/specification/columns/publisher.md index a9f5fd16c..14a407167 100644 --- a/specification/columns/publisher.md +++ b/specification/columns/publisher.md @@ -2,7 +2,7 @@ A Publisher is an entity that produces the [*resources*](#glossary:resource) or [*services*](#glossary:service) that were purchased. It is commonly used for cost analysis and reporting scenarios. -The Publisher column MUST be present in a FOCUS dataset. This column MUST be of type String and MUST NOT contain null values. +The Publisher column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset). This column MUST be of type String and MUST NOT contain null values. See [Appendix: Origination of cost data](#originationofcostdata) section for examples of [Provider](#provider), Publisher and [Invoice Issuer](#invoiceissuer) values that can be used for various purchasing scenarios. diff --git a/specification/columns/regionid.md b/specification/columns/regionid.md index 873d036df..b1cada0e4 100644 --- a/specification/columns/regionid.md +++ b/specification/columns/regionid.md @@ -2,7 +2,7 @@ A Region ID is a provider-assigned identifier for an isolated geographic area where a [*resource*](#glossary:resource) is provisioned or a [*service*](#glossary:service) is provided. The region is commonly used for scenarios like analyzing cost and unit prices based on where *resources* are deployed. -The RegionId column MUST be present in a FOCUS dataset when the provider supports deploying resources or services within a *region* and MUST be of type String. RegionId MUST NOT be null when a *resource* or *service* is operated in or managed from a distinct region by the Provider and MAY contain null values when a *resource* or *service* is not restricted to an isolated geographic area. +The RegionId column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports deploying resources or services within a *region* and MUST be of type String. RegionId MUST NOT be null when a *resource* or *service* is operated in or managed from a distinct region by the Provider and MAY contain null values when a *resource* or *service* is not restricted to an isolated geographic area. ## Column ID diff --git a/specification/columns/regionname.md b/specification/columns/regionname.md index 934ca0b91..ee3092e51 100644 --- a/specification/columns/regionname.md +++ b/specification/columns/regionname.md @@ -2,7 +2,7 @@ Region Name is a provider-assigned display name for an isolated geographic area where a [*resource*](#glossary:resource) is provisioned or a [*service*](#glossary:service) is provided. Region Name is commonly used for scenarios like analyzing cost and unit prices based on where *resources* are deployed. -The RegionName column MUST be present in a FOCUS dataset when the provider supports deploying resources or services within a *region* and MUST be of type String. RegionName MUST NOT be null when a *resource* or *service* is operated in or managed from a distinct region by the Provider and MAY contain null values when a *resource* or *service* is not restricted to an isolated geographic area. +The RegionName column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports deploying resources or services within a *region* and MUST be of type String. RegionName MUST NOT be null when a *resource* or *service* is operated in or managed from a distinct region by the Provider and MAY contain null values when a *resource* or *service* is not restricted to an isolated geographic area. ## Column ID diff --git a/specification/columns/resourceid.md b/specification/columns/resourceid.md index e48d24d08..f494aa480 100644 --- a/specification/columns/resourceid.md +++ b/specification/columns/resourceid.md @@ -2,7 +2,7 @@ A Resource ID is an identifier assigned to a [*resource*](#glossary:resource) by the provider. The Resource ID is commonly used for cost reporting, analysis, and allocation scenarios. -The ResourceId column MUST be present in a FOCUS dataset when the provider supports billing based on provisioned resources. This column MUST be of type String. The ResourceId value MAY be a nullable column as some cost data [*rows*](#glossary:row) may not be associated with a *resource*. ResourceId MUST appear in the cost data if an identifier is assigned to a *resource* by the provider. ResourceId SHOULD be a fully-qualified identifier that ensures global uniqueness within the provider. +The ResourceId column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports billing based on provisioned resources. This column MUST be of type String. The ResourceId value MAY be a nullable column as some cost data [*rows*](#glossary:row) may not be associated with a *resource*. ResourceId MUST appear in the cost data if an identifier is assigned to a *resource* by the provider. ResourceId SHOULD be a fully-qualified identifier that ensures global uniqueness within the provider. ## Column ID diff --git a/specification/columns/resourcename.md b/specification/columns/resourcename.md index 524311b0c..71fa7a938 100644 --- a/specification/columns/resourcename.md +++ b/specification/columns/resourcename.md @@ -2,7 +2,7 @@ The Resource Name is a display name assigned to a [*resource*](#glossary:resource). It is commonly used for cost analysis, reporting, and allocation scenarios. -The ResourceName column MUST be present in a FOCUS dataset when the provider supports billing based on provisioned resources. This column MUST be of type String. The ResourceName value MAY be a nullable column as some cost data [*rows*](#glossary:row) may not be associated with a *resource* or because a display name cannot be assigned to a *resource*. ResourceName MUST NOT be null if a display name can be assigned to a *resource*. *Resources* not provisioned interactively or only have a system-generated [ResourceId](#resourceid) MUST NOT duplicate the same value as the ResourceName. +The ResourceName column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports billing based on provisioned resources. This column MUST be of type String. The ResourceName value MAY be a nullable column as some cost data [*rows*](#glossary:row) may not be associated with a *resource* or because a display name cannot be assigned to a *resource*. ResourceName MUST NOT be null if a display name can be assigned to a *resource*. *Resources* not provisioned interactively or only have a system-generated [ResourceId](#resourceid) MUST NOT duplicate the same value as the ResourceName. ## Column ID diff --git a/specification/columns/resourcetype.md b/specification/columns/resourcetype.md index 96480f78a..d05622c87 100644 --- a/specification/columns/resourcetype.md +++ b/specification/columns/resourcetype.md @@ -2,7 +2,7 @@ Resource Type describes the kind of [*resource*](#glossary:resource) the charge applies to. A Resource Type is commonly used for scenarios like identifying cost changes in groups of similar *resources* and may include values like Virtual Machine, Data Warehouse, and Load Balancer. -The ResourceType column MUST be present in a FOCUS dataset when the provider supports billing based on provisioned resources and supports assigning a type for resources. This column MUST be of type String and MUST NOT be null when a corresponding [ResourceId](#resourceid) is not null. When a corresponding ResourceId value is null, the ResourceType column value MUST also be null. +The ResourceType column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports billing based on provisioned resources and supports assigning a type for resources. This column MUST be of type String and MUST NOT be null when a corresponding [ResourceId](#resourceid) is not null. When a corresponding ResourceId value is null, the ResourceType column value MUST also be null. ## Column ID diff --git a/specification/columns/servicecategory.md b/specification/columns/servicecategory.md index c8d474fbb..77a83c41e 100644 --- a/specification/columns/servicecategory.md +++ b/specification/columns/servicecategory.md @@ -2,7 +2,7 @@ The Service Category is the highest-level classification of a [*service*](#glossary:service) based on the core function of the *service*. Each *service* should have one and only one category that best aligns with its primary purpose. The Service Category is commonly used for scenarios like analyzing costs across providers and tracking the migration of workloads across fundamentally different architectures. -The ServiceCategory column MUST be present in a FOCUS dataset and MUST NOT be null. This column is of type String and MUST be one of the allowed values. +The ServiceCategory column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) and MUST NOT be null. This column is of type String and MUST be one of the allowed values. ## Column ID diff --git a/specification/columns/servicename.md b/specification/columns/servicename.md index db1fc0cda..a5086cba1 100644 --- a/specification/columns/servicename.md +++ b/specification/columns/servicename.md @@ -4,7 +4,7 @@ A [*service*](#glossary:service) represents an offering that can be purchased fr The Service Name is a display name for the offering that was purchased. The Service Name is commonly used for scenarios like analyzing aggregate cost trends over time and filtering data to investigate anomalies. -The ServiceName column MUST be present in a FOCUS dataset. This column MUST be of type String and MUST NOT contain null values. +The ServiceName column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset). This column MUST be of type String and MUST NOT contain null values. ## Column ID diff --git a/specification/columns/servicesubcategory.md b/specification/columns/servicesubcategory.md index f235967fb..8452e588b 100644 --- a/specification/columns/servicesubcategory.md +++ b/specification/columns/servicesubcategory.md @@ -4,7 +4,7 @@ The Service Subcategory is a secondary classification of the [Service Category]( The ServiceSubcategory column adheres to the following requirements: -* ServiceSubcategory is RECOMMENDED to be present in a FOCUS dataset and MUST NOT be null. +* ServiceSubcategory is RECOMMENDED to be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) and MUST NOT be null. * ServiceSubcategory is of type String and MUST be one of the allowed values. * Each ServiceSubcategory value MUST have one and only one parent ServiceCategory as specified in the allowed values below. * Though a given *service* can have multiple purposes, each *service* SHOULD have one and only one ServiceSubcategory that best aligns with its primary purpose. diff --git a/specification/columns/skuid.md b/specification/columns/skuid.md index 7ab6ce38d..584a54416 100644 --- a/specification/columns/skuid.md +++ b/specification/columns/skuid.md @@ -2,7 +2,7 @@ A SKU ID is a unique identifier that defines a provider-supported construct for organizing properties that are common across one or more [*SKU Prices*](#glossary:sku-price). SKU ID can be referenced on a catalog or [*price list*](#glossary:price-list) published by a provider to look up detailed information about the SKU. The composition of the properties associated with the SKU ID may differ across providers. Some providers may not support the [*SKU*](#glossary:sku) construct and instead associate all such properties directly with the *SKU Price*. SKU ID is commonly used for analyzing cost based on *SKU*-related properties above the pricing constructs. -The SkuId column MUST be present in a FOCUS dataset when the provider publishes a SKU list. This column MUST be of type String. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. SkuId MUST equal SkuPriceId when a provider does not support an overarching SKU ID construct. +The SkuId column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider publishes a SKU list. This column MUST be of type String. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. SkuId MUST equal SkuPriceId when a provider does not support an overarching SKU ID construct. ## Column ID diff --git a/specification/columns/skumeter.md b/specification/columns/skumeter.md index 6b642abe2..bdd892b9a 100644 --- a/specification/columns/skumeter.md +++ b/specification/columns/skumeter.md @@ -2,11 +2,11 @@ The SKU Meter describes the functionality being metered or measured by a particular SKU in a charge. -Providers often have billing models in which multiple SKUs exist for a given service to describe and bill for different functionalities for that service. For example, an object storage service may have separate SKUs for functionalities such as object storage, API requests, data transfer, encryption, and object management. This field helps practitioners understand which functionalities are being metered by the different SKUs that appear in a FOCUS dataset. +Providers often have billing models in which multiple SKUs exist for a given service to describe and bill for different functionalities for that service. For example, an object storage service may have separate SKUs for functionalities such as object storage, API requests, data transfer, encryption, and object management. This field helps practitioners understand which functionalities are being metered by the different SKUs that appear in a [*FOCUS dataset*](#glossary:FOCUS-dataset). The SkuMeter column adheres to the following requirements: -* SkuMeter MUST be present in the billing data when when the provider includes a [SkuId](#skuid). +* SkuMeter MUST be present in a *FOCUS dataset* when when the provider includes a [SkuId](#skuid). * SkuMeter MUST be of type String. * SkuMeter MUST be null when SkuId is null. * SkuMeter SHOULD NOT be null when SkuId is not null. diff --git a/specification/columns/subaccountid.md b/specification/columns/subaccountid.md index f0bfd2a4a..7ca7ccd62 100644 --- a/specification/columns/subaccountid.md +++ b/specification/columns/subaccountid.md @@ -2,7 +2,7 @@ A Sub Account ID is a provider-assigned identifier assigned to a [*sub account*](#glossary:sub-account). Sub Account ID is commonly used for scenarios like grouping based on organizational constructs, access management needs, and cost allocation strategies. -The SubAccountId column MUST be present in a FOCUS dataset when the provider supports a *sub account* construct. This column MUST be of type String. If a charge does not apply to a *sub account*, the SubAccountId column MUST be null. +The SubAccountId column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports a *sub account* construct. This column MUST be of type String. If a charge does not apply to a *sub account*, the SubAccountId column MUST be null. See [Appendix: Grouping constructs for resources or services](#groupingconstructsforresourcesorservices) for details and examples of the different grouping constructs supported by FOCUS. diff --git a/specification/columns/subaccountname.md b/specification/columns/subaccountname.md index 0f837ecec..b64f56fd6 100644 --- a/specification/columns/subaccountname.md +++ b/specification/columns/subaccountname.md @@ -2,7 +2,7 @@ A Sub Account Name is a display name assigned to a [*sub account*](#glossary:sub-account). Sub account Name is commonly used for scenarios like grouping based on organizational constructs, access management needs, and cost allocation strategies. -The SubAccountName column MUST be present in a FOCUS dataset when the provider supports a *sub account* construct. This column MUST be of type String. If a charge does not apply to a *sub account*, the SubAccountName column MUST be null. +The SubAccountName column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports a *sub account* construct. This column MUST be of type String. If a charge does not apply to a *sub account*, the SubAccountName column MUST be null. See [Appendix: Grouping constructs for resources or services](#groupingconstructsforresourcesorservices) for details and examples of the different grouping constructs supported by FOCUS. diff --git a/specification/columns/tags.md b/specification/columns/tags.md index 4a9c8039e..d273fa195 100644 --- a/specification/columns/tags.md +++ b/specification/columns/tags.md @@ -6,7 +6,7 @@ A tag becomes [*finalized*](#glossary:finalized-tag) when a single value is sele The Tags column adheres to the following requirements: -* The Tags column MUST be present in a FOCUS dataset when the provider supports setting user or provider-defined tags. +* The Tags column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports setting user or provider-defined tags. * The Tags column MUST contain user-defined and provider-defined tags. * The Tags column MUST only contain finalized tags. * The Tags column MUST be in [KeyValueFormat](#key-valueformat). diff --git a/specification/metadata/data_generator/datagenerator.md b/specification/metadata/data_generator/datagenerator.md index abc636b46..64ed31dca 100644 --- a/specification/metadata/data_generator/datagenerator.md +++ b/specification/metadata/data_generator/datagenerator.md @@ -2,7 +2,7 @@ Human-readable name of the entity that is generating the data. -The DataGenerator MUST be provided in the metadata. DataGenerator MUST be of type String and MUST NOT be null. The DataGenerator SHOULD be easily associated with the provider who generated the FOCUS dataset. +The DataGenerator MUST be provided in the metadata. DataGenerator MUST be of type String and MUST NOT be null. The DataGenerator SHOULD be easily associated with the provider who generated the [*FOCUS dataset*](#glossary:FOCUS-dataset). ## Metadata ID diff --git a/specification/metadata/metadata.mdpp b/specification/metadata/metadata.mdpp index 46a776168..128078fe5 100644 --- a/specification/metadata/metadata.mdpp +++ b/specification/metadata/metadata.mdpp @@ -1,6 +1,6 @@ # Metadata -The FOCUS specification defines a metadata structure to be supplied by data providers to facilitate practitioners' use of FOCUS data. This metadata includes general information about the data generator and the schema of the FOCUS dataset. +The FOCUS specification defines a metadata structure to be supplied by data providers to facilitate practitioners' use of FOCUS data. This metadata includes general information about the data generator and the schema of the [*FOCUS dataset*](#glossary:FOCUS-dataset). FOCUS Metadata SHOULD be provided in a format that is accessible programmatically, such as a file, website, API, or table. Providers SHOULD provide documentation on their implementation of the FOCUS metadata. diff --git a/specification/metadata/schema/column_definition/column_definition.mdpp b/specification/metadata/schema/column_definition/column_definition.mdpp index 18a2f8490..71ef1132e 100644 --- a/specification/metadata/schema/column_definition/column_definition.mdpp +++ b/specification/metadata/schema/column_definition/column_definition.mdpp @@ -1,6 +1,6 @@ # Column Definition -The FOCUS metadata schema column definition provides a list of the columns present in the FOCUS dataset along with metadata about the columns. +The FOCUS metadata schema column definition provides a list of the columns present in the [*FOCUS dataset*](#glossary:FOCUS-dataset) along with metadata about the columns. ## Requirements diff --git a/specification/metadata/schema/column_definition/columnname.md b/specification/metadata/schema/column_definition/columnname.md index bd6b40f96..0762433e9 100644 --- a/specification/metadata/schema/column_definition/columnname.md +++ b/specification/metadata/schema/column_definition/columnname.md @@ -1,6 +1,6 @@ # Column Name -The name of the column provided in the FOCUS dataset. +The name of the column provided in the [*FOCUS dataset*](#glossary:FOCUS-dataset). The ColumnName MUST be provided in the FOCUS Metadata schema. ColumnName MUST be of type String and MUST NOT contain null values. diff --git a/specification/metadata/schema/column_definition/datatype.md b/specification/metadata/schema/column_definition/datatype.md index 8a33adbca..bbd6b2eea 100644 --- a/specification/metadata/schema/column_definition/datatype.md +++ b/specification/metadata/schema/column_definition/datatype.md @@ -1,6 +1,6 @@ # Data Type -The data type of the column provided in the FOCUS dataset. +The data type of the column provided in the [*FOCUS dataset*](#glossary:FOCUS-dataset). The DataType MUST be provided in the FOCUS Metadata schema. DataType MUST be of type String and MUST NOT contain null values. diff --git a/specification/metadata/schema/column_definition/providertagprefixes.md b/specification/metadata/schema/column_definition/providertagprefixes.md index ca8ddb4b6..5fdfc278b 100644 --- a/specification/metadata/schema/column_definition/providertagprefixes.md +++ b/specification/metadata/schema/column_definition/providertagprefixes.md @@ -2,7 +2,7 @@ The Provider Tag Prefixes defines the list of prefixes used in the tag name of provider-defined [tags](#tags). This metadata is useful for the consumer to identify which tags are provider-defined vs user-defined. -The ProviderTagPrefixes MUST be provided when ColumnName is equal to Tags. The ProviderTagPrefix MUST be of type Array of Strings. The ProviderTagPrefixes SHOULD be easily associated with the provider who generated the FOCUS dataset. +The ProviderTagPrefixes MUST be provided when ColumnName is equal to Tags. The ProviderTagPrefix MUST be of type Array of Strings. The ProviderTagPrefixes SHOULD be easily associated with the provider who generated the [*FOCUS dataset*](#glossary:FOCUS-dataset). ## Metadata ID diff --git a/specification/metadata/schema/column_definition/stringencoding.md b/specification/metadata/schema/column_definition/stringencoding.md index 49f7fba22..ae790dee1 100644 --- a/specification/metadata/schema/column_definition/stringencoding.md +++ b/specification/metadata/schema/column_definition/stringencoding.md @@ -1,6 +1,6 @@ # String Encoding -The string encoding scheme of the column provided in the FOCUS dataset. +The string encoding scheme of the column provided in the [*FOCUS dataset*](#glossary:FOCUS-dataset). StringEncoding SHOULD be provided in the FOCUS Metadata schema when it is required to know this information in order to successfully read the data. StringEncoding MUST be of type String and MUST NOT contain null values. diff --git a/specification/metadata/schema/focusversion.md b/specification/metadata/schema/focusversion.md index 323b54428..0950e42a5 100644 --- a/specification/metadata/schema/focusversion.md +++ b/specification/metadata/schema/focusversion.md @@ -2,7 +2,7 @@ The version of FOCUS utilized for building the dataset. -The FocusVersion MUST be provided in the metadata. FocusVersion MUST be of type String and MUST NOT contain null values. FocusVersion MUST match one of the published versions of the FOCUS specification. FocusVersion MUST match the version of the FOCUS specification that the FOCUS dataset conforms to. +The FocusVersion MUST be provided in the metadata. FocusVersion MUST be of type String and MUST NOT contain null values. FocusVersion MUST match one of the published versions of the FOCUS specification. FocusVersion MUST match the version of the FOCUS specification that the [*FOCUS dataset*](#glossary:FOCUS-dataset) conforms to. ## Metadata ID diff --git a/specification/metadata/schema/providerversion.md b/specification/metadata/schema/providerversion.md index bcf3ebe6d..0b0c8450c 100644 --- a/specification/metadata/schema/providerversion.md +++ b/specification/metadata/schema/providerversion.md @@ -1,6 +1,6 @@ # Provider Version -The ProviderVersion MAY be supplied to declare the version of logic by which the FOCUS dataset was generated and is separate from FOCUS Version. ProviderVersion allows for the provider to specify changes that may not result in a structural change in the data. It is suggested that the provider version use a versioning approach such as [SemVer](https://semver.org) version. +The ProviderVersion MAY be supplied to declare the version of logic by which the [*FOCUS dataset*](#glossary:FOCUS-dataset) was generated and is separate from FOCUS Version. ProviderVersion allows for the provider to specify changes that may not result in a structural change in the data. It is suggested that the provider version use a versioning approach such as [SemVer](https://semver.org) version. ProviderVersion MUST be of type String and MUST NOT contain null values. If FocusVersion is changed a new ProviderVersion MUST be also changed. The provider MUST document what changes are present in the ProviderVersion. diff --git a/specification/metadata/schema/schema.mdpp b/specification/metadata/schema/schema.mdpp index 50825a4fe..8f40cc61b 100644 --- a/specification/metadata/schema/schema.mdpp +++ b/specification/metadata/schema/schema.mdpp @@ -8,7 +8,7 @@ The schema metadata object and its contents provides information about the struc FOCUS data artifacts, whether they are data files, data streams, or data tables, MUST provide a clear reference to the schema of the data. This reference MUST be retrievable without inspection of the contents of the FOCUS data within the data artifact. For some delivery mechanisms such as database tables, the provider may rely on the schema functionality of the providing system. -It is recommended that the schema reference be provided as an external reference rather than included in full as metadata accompanying the data artifact. This allows for easier understanding of when changes to the schema of the FOCUS datasets occurs. +It is recommended that the schema reference be provided as an external reference rather than included in full as metadata accompanying the data artifact. This allows for easier understanding of when changes to the schema of the [*FOCUS datasets*](#glossary:FOCUS-dataset) occurs. ### Schema Metadata Creation From e30cf6bc7a71e152e309158b4affb825b30e891c Mon Sep 17 00:00:00 2001 From: Joaquin Date: Tue, 8 Oct 2024 23:31:48 -0700 Subject: [PATCH 52/52] [ADMIN] Update README.md (#597) [ADMIN] Blank PR to trigger a build. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index fd92a2516..2884b0591 100644 --- a/README.md +++ b/README.md @@ -47,3 +47,4 @@ See the [project repository](https://github.com/FinOps-Open-Cost-and-Usage-Spec/ - [Change / contribution process](https://github.com/FinOps-Open-Cost-and-Usage-Spec/foundation/blob/main/contributing.md) +