From 98309cbd10dc9141affe73f252a6df6995248da5 Mon Sep 17 00:00:00 2001 From: Brendan Hy Date: Mon, 26 Oct 2026 14:28:34 -0700 Subject: [PATCH 1/8] feat(billing): Expose when PAYG spend exceeds its budget --- .../usage_pricer/v1/endpoint_usage_pricer.proto | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/proto/sentry_protos/billing/v1/services/usage_pricer/v1/endpoint_usage_pricer.proto b/proto/sentry_protos/billing/v1/services/usage_pricer/v1/endpoint_usage_pricer.proto index 56de506c..eb424652 100644 --- a/proto/sentry_protos/billing/v1/services/usage_pricer/v1/endpoint_usage_pricer.proto +++ b/proto/sentry_protos/billing/v1/services/usage_pricer/v1/endpoint_usage_pricer.proto @@ -94,6 +94,13 @@ message LineItemUsageSummary { // grants are applied, but before reserved quantity is deducted. This includes // both reserved and PAYG usage (in the line item's units). uint64 non_granted_quantity = 9; + + // True when pre-cap PAYG spend exceeds the applicable budget and must be + // reduced. For an all-items budget, reflects overflow of the entire budget. + // Exactly consuming the budget exhausts it without exceeding it. + // False when no PAYG budget applies; this alone does not establish PAYG + // eligibility. + bool exceeded_payg_budget = 10; } message SharedLineItemUsageSummary { @@ -111,6 +118,10 @@ message SharedLineItemUsageSummary { // True when any member of this pool can continue accepting usage. bool has_remaining_capacity = 5; + + // True when any member's applicable PAYG budget was exceeded. + // Exactly consuming a budget exhausts it without exceeding it. + bool exceeded_payg_budget = 6; } // One project's per-day outcomes. Only days and line items with usage From c23e70e5f7ee40f620d13aa044ed243881198c96 Mon Sep 17 00:00:00 2001 From: "getsantry[bot]" <66042841+getsantry[bot]@users.noreply.github.com> Date: Mon, 26 Oct 2026 21:29:44 +0000 Subject: [PATCH 2/8] chore: Regenerate Rust bindings --- Cargo.lock | 2 +- ...ntry_protos.billing.v1.services.usage_pricer.v1.rs | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 09d2f89c..0af9158c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -717,7 +717,7 @@ checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "sentry_protos" -version = "0.90.0" +version = "0.91.0" dependencies = [ "prost", "prost-types", diff --git a/rust/src/sentry_protos.billing.v1.services.usage_pricer.v1.rs b/rust/src/sentry_protos.billing.v1.services.usage_pricer.v1.rs index 295f6307..551558c8 100644 --- a/rust/src/sentry_protos.billing.v1.services.usage_pricer.v1.rs +++ b/rust/src/sentry_protos.billing.v1.services.usage_pricer.v1.rs @@ -151,6 +151,13 @@ pub struct LineItemUsageSummary { /// both reserved and PAYG usage (in the line item's units). #[prost(uint64, tag = "9")] pub non_granted_quantity: u64, + /// True when pre-cap PAYG spend exceeds the applicable budget and must be + /// reduced. For an all-items budget, reflects overflow of the entire budget. + /// Exactly consuming the budget exhausts it without exceeding it. + /// False when no PAYG budget applies; this alone does not establish PAYG + /// eligibility. + #[prost(bool, tag = "10")] + pub exceeded_payg_budget: bool, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct SharedLineItemUsageSummary { @@ -169,6 +176,10 @@ pub struct SharedLineItemUsageSummary { /// True when any member of this pool can continue accepting usage. #[prost(bool, tag = "5")] pub has_remaining_capacity: bool, + /// True when any member's applicable PAYG budget was exceeded. + /// Exactly consuming a budget exhausts it without exceeding it. + #[prost(bool, tag = "6")] + pub exceeded_payg_budget: bool, } /// One project's per-day outcomes. Only days and line items with usage /// are present; anything missing had no usage. From 73957987ad06e18ed74be68d0160acd4bf7ea67b Mon Sep 17 00:00:00 2001 From: Brendan Hy Date: Mon, 26 Oct 2026 14:40:18 -0700 Subject: [PATCH 3/8] docs(billing): Define missing PAYG budgets as zero allowance --- .../services/usage_pricer/v1/endpoint_usage_pricer.proto | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/proto/sentry_protos/billing/v1/services/usage_pricer/v1/endpoint_usage_pricer.proto b/proto/sentry_protos/billing/v1/services/usage_pricer/v1/endpoint_usage_pricer.proto index eb424652..1eb78951 100644 --- a/proto/sentry_protos/billing/v1/services/usage_pricer/v1/endpoint_usage_pricer.proto +++ b/proto/sentry_protos/billing/v1/services/usage_pricer/v1/endpoint_usage_pricer.proto @@ -95,11 +95,11 @@ message LineItemUsageSummary { // both reserved and PAYG usage (in the line item's units). uint64 non_granted_quantity = 9; - // True when pre-cap PAYG spend exceeds the applicable budget and must be - // reduced. For an all-items budget, reflects overflow of the entire budget. + // True when pre-cap PAYG spend exceeds the effective PAYG allowance. + // Missing budgets and disabled PAYG allow zero spend. For an all-items + // budget, reflects overflow of the entire budget. // Exactly consuming the budget exhausts it without exceeding it. - // False when no PAYG budget applies; this alone does not establish PAYG - // eligibility. + // False does not establish PAYG eligibility when there is no priced usage. bool exceeded_payg_budget = 10; } From 2ec77da5fe1ed00a453fdfb9c66d94e944a3d76d Mon Sep 17 00:00:00 2001 From: "getsantry[bot]" <66042841+getsantry[bot]@users.noreply.github.com> Date: Mon, 26 Oct 2026 21:41:32 +0000 Subject: [PATCH 4/8] chore: Regenerate Rust bindings --- .../sentry_protos.billing.v1.services.usage_pricer.v1.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rust/src/sentry_protos.billing.v1.services.usage_pricer.v1.rs b/rust/src/sentry_protos.billing.v1.services.usage_pricer.v1.rs index 551558c8..d026ded3 100644 --- a/rust/src/sentry_protos.billing.v1.services.usage_pricer.v1.rs +++ b/rust/src/sentry_protos.billing.v1.services.usage_pricer.v1.rs @@ -151,11 +151,11 @@ pub struct LineItemUsageSummary { /// both reserved and PAYG usage (in the line item's units). #[prost(uint64, tag = "9")] pub non_granted_quantity: u64, - /// True when pre-cap PAYG spend exceeds the applicable budget and must be - /// reduced. For an all-items budget, reflects overflow of the entire budget. + /// True when pre-cap PAYG spend exceeds the effective PAYG allowance. + /// Missing budgets and disabled PAYG allow zero spend. For an all-items + /// budget, reflects overflow of the entire budget. /// Exactly consuming the budget exhausts it without exceeding it. - /// False when no PAYG budget applies; this alone does not establish PAYG - /// eligibility. + /// False does not establish PAYG eligibility when there is no priced usage. #[prost(bool, tag = "10")] pub exceeded_payg_budget: bool, } From 2bb61339b939aeec17575bcc2a692c854dbbb83a Mon Sep 17 00:00:00 2001 From: Brendan Hy Date: Mon, 26 Oct 2026 14:47:05 -0700 Subject: [PATCH 5/8] docs(billing): Explain PAYG overflow with an exact-fit example --- .../usage_pricer/v1/endpoint_usage_pricer.proto | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/proto/sentry_protos/billing/v1/services/usage_pricer/v1/endpoint_usage_pricer.proto b/proto/sentry_protos/billing/v1/services/usage_pricer/v1/endpoint_usage_pricer.proto index 1eb78951..dc1580b4 100644 --- a/proto/sentry_protos/billing/v1/services/usage_pricer/v1/endpoint_usage_pricer.proto +++ b/proto/sentry_protos/billing/v1/services/usage_pricer/v1/endpoint_usage_pricer.proto @@ -95,11 +95,9 @@ message LineItemUsageSummary { // both reserved and PAYG usage (in the line item's units). uint64 non_granted_quantity = 9; - // True when pre-cap PAYG spend exceeds the effective PAYG allowance. - // Missing budgets and disabled PAYG allow zero spend. For an all-items - // budget, reflects overflow of the entire budget. - // Exactly consuming the budget exhausts it without exceeding it. - // False does not establish PAYG eligibility when there is no priced usage. + // True when PAYG spend is greater than the budget. + // For example, a $1 allocation against a $1 budget returns false. + // For an all-items budget, compares the total spend across its line items. bool exceeded_payg_budget = 10; } @@ -119,8 +117,7 @@ message SharedLineItemUsageSummary { // True when any member of this pool can continue accepting usage. bool has_remaining_capacity = 5; - // True when any member's applicable PAYG budget was exceeded. - // Exactly consuming a budget exhausts it without exceeding it. + // True when any member's PAYG spend is greater than its budget. bool exceeded_payg_budget = 6; } From dce5d39a8e85675e356da181896b6cfe09ff7fa8 Mon Sep 17 00:00:00 2001 From: "getsantry[bot]" <66042841+getsantry[bot]@users.noreply.github.com> Date: Mon, 26 Oct 2026 21:48:02 +0000 Subject: [PATCH 6/8] chore: Regenerate Rust bindings --- ...ntry_protos.billing.v1.services.usage_pricer.v1.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/rust/src/sentry_protos.billing.v1.services.usage_pricer.v1.rs b/rust/src/sentry_protos.billing.v1.services.usage_pricer.v1.rs index d026ded3..3cefbb1c 100644 --- a/rust/src/sentry_protos.billing.v1.services.usage_pricer.v1.rs +++ b/rust/src/sentry_protos.billing.v1.services.usage_pricer.v1.rs @@ -151,11 +151,9 @@ pub struct LineItemUsageSummary { /// both reserved and PAYG usage (in the line item's units). #[prost(uint64, tag = "9")] pub non_granted_quantity: u64, - /// True when pre-cap PAYG spend exceeds the effective PAYG allowance. - /// Missing budgets and disabled PAYG allow zero spend. For an all-items - /// budget, reflects overflow of the entire budget. - /// Exactly consuming the budget exhausts it without exceeding it. - /// False does not establish PAYG eligibility when there is no priced usage. + /// True when PAYG spend is greater than the budget. + /// For example, a $1 allocation against a $1 budget returns false. + /// For an all-items budget, compares the total spend across its line items. #[prost(bool, tag = "10")] pub exceeded_payg_budget: bool, } @@ -176,8 +174,7 @@ pub struct SharedLineItemUsageSummary { /// True when any member of this pool can continue accepting usage. #[prost(bool, tag = "5")] pub has_remaining_capacity: bool, - /// True when any member's applicable PAYG budget was exceeded. - /// Exactly consuming a budget exhausts it without exceeding it. + /// True when any member's PAYG spend is greater than its budget. #[prost(bool, tag = "6")] pub exceeded_payg_budget: bool, } From 523690362a165c9492ebffdd540c48faf41ad12e Mon Sep 17 00:00:00 2001 From: Brendan Hy Date: Mon, 26 Oct 2026 15:50:04 -0700 Subject: [PATCH 7/8] ref(billing): Deprecate budget exhaustion summary fields --- .../services/usage_pricer/v1/endpoint_usage_pricer.proto | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/proto/sentry_protos/billing/v1/services/usage_pricer/v1/endpoint_usage_pricer.proto b/proto/sentry_protos/billing/v1/services/usage_pricer/v1/endpoint_usage_pricer.proto index dc1580b4..c7c388cc 100644 --- a/proto/sentry_protos/billing/v1/services/usage_pricer/v1/endpoint_usage_pricer.proto +++ b/proto/sentry_protos/billing/v1/services/usage_pricer/v1/endpoint_usage_pricer.proto @@ -67,14 +67,14 @@ message LineItemUsageSummary { uint64 quantity = 3; // Whether the usage pricer had to cap the spend based on the budget set by the contract - bool payg_budget_exhausted = 4; + bool payg_budget_exhausted = 4 [deprecated = true]; // false when this line item still has reserved quantity left. // It's possible that PAYG is exhausted whereas reserved is not. // Example: there's an overall PAYG budget of $10, a customer sends $10 worth of errors // the payg_budget_exhausted field is true for all line items // however, the plan still includes 5GB of free logs, so reserved_budget_exhausted is false for logs. - bool reserved_budget_exhausted = 5; + bool reserved_budget_exhausted = 5 [deprecated = true]; // Total units consumed by this line item in the billing period, including // both reserved and PAYG usage (in the line item's units). Unlike `quantity`, @@ -109,10 +109,10 @@ message SharedLineItemUsageSummary { repeated LineItemUsageSummary line_item_summaries = 2; // Whether the usage pricer had to cap the spend based on the budget set by the contract - bool payg_budget_exhausted = 3; + bool payg_budget_exhausted = 3 [deprecated = true]; // false when this pool still has reserved quantity left. - bool reserved_budget_exhausted = 4; + bool reserved_budget_exhausted = 4 [deprecated = true]; // True when any member of this pool can continue accepting usage. bool has_remaining_capacity = 5; From 2ba198a38124fecb07ac98d919850501e6108733 Mon Sep 17 00:00:00 2001 From: "getsantry[bot]" <66042841+getsantry[bot]@users.noreply.github.com> Date: Mon, 26 Oct 2026 22:51:11 +0000 Subject: [PATCH 8/8] chore: Regenerate Rust bindings --- rust/src/sentry_protos.billing.v1.services.usage_pricer.v1.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rust/src/sentry_protos.billing.v1.services.usage_pricer.v1.rs b/rust/src/sentry_protos.billing.v1.services.usage_pricer.v1.rs index 3cefbb1c..1ce586f2 100644 --- a/rust/src/sentry_protos.billing.v1.services.usage_pricer.v1.rs +++ b/rust/src/sentry_protos.billing.v1.services.usage_pricer.v1.rs @@ -123,6 +123,7 @@ pub struct LineItemUsageSummary { #[prost(uint64, tag = "3")] pub quantity: u64, /// Whether the usage pricer had to cap the spend based on the budget set by the contract + #[deprecated] #[prost(bool, tag = "4")] pub payg_budget_exhausted: bool, /// false when this line item still has reserved quantity left. @@ -130,6 +131,7 @@ pub struct LineItemUsageSummary { /// Example: there's an overall PAYG budget of $10, a customer sends $10 worth of errors /// the payg_budget_exhausted field is true for all line items /// however, the plan still includes 5GB of free logs, so reserved_budget_exhausted is false for logs. + #[deprecated] #[prost(bool, tag = "5")] pub reserved_budget_exhausted: bool, /// Total units consumed by this line item in the billing period, including @@ -166,9 +168,11 @@ pub struct SharedLineItemUsageSummary { #[prost(message, repeated, tag = "2")] pub line_item_summaries: ::prost::alloc::vec::Vec, /// Whether the usage pricer had to cap the spend based on the budget set by the contract + #[deprecated] #[prost(bool, tag = "3")] pub payg_budget_exhausted: bool, /// false when this pool still has reserved quantity left. + #[deprecated] #[prost(bool, tag = "4")] pub reserved_budget_exhausted: bool, /// True when any member of this pool can continue accepting usage.