From 0a7bf1069f077f85bea5f54aabc5cfab07f3fc38 Mon Sep 17 00:00:00 2001 From: Phil Bastian Date: Wed, 10 Jun 2026 09:40:54 +0800 Subject: [PATCH] provide monthly throughput values to the licensing API --- .../EndpointThroughputSummary.cs | 5 ++++- src/Particular.LicensingComponent/ThroughputCollector.cs | 1 + .../ThroughputDataExtensions.cs | 5 +++++ .../Throughput/LicensingDataStore.cs | 2 +- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Particular.LicensingComponent.Contracts/EndpointThroughputSummary.cs b/src/Particular.LicensingComponent.Contracts/EndpointThroughputSummary.cs index 5c6cd7392c..7860ae8eec 100644 --- a/src/Particular.LicensingComponent.Contracts/EndpointThroughputSummary.cs +++ b/src/Particular.LicensingComponent.Contracts/EndpointThroughputSummary.cs @@ -7,6 +7,7 @@ public class EndpointThroughputSummary public bool IsKnownEndpoint { get; set; } public string UserIndicator { get; set; } public long MaxDailyThroughput { get; set; } + public MonthlyThroughput[] MonthlyThroughput { get; set; } public long MaxMonthlyThroughput { get; set; } } @@ -14,4 +15,6 @@ public class UpdateUserIndicator { public string Name { get; set; } public string UserIndicator { get; set; } -} \ No newline at end of file +} + +public record MonthlyThroughput(string Month, long Throughput); \ No newline at end of file diff --git a/src/Particular.LicensingComponent/ThroughputCollector.cs b/src/Particular.LicensingComponent/ThroughputCollector.cs index 4e18741612..925cc203c0 100644 --- a/src/Particular.LicensingComponent/ThroughputCollector.cs +++ b/src/Particular.LicensingComponent/ThroughputCollector.cs @@ -73,6 +73,7 @@ public async Task> GetThroughputSummary(Cancella UserIndicator = endpointData.UserIndicator ?? (endpointData.IsKnownEndpoint ? Contracts.UserIndicator.NServiceBusEndpoint.ToString() : string.Empty), IsKnownEndpoint = endpointData.IsKnownEndpoint, MaxDailyThroughput = endpointData.ThroughputData.MaxDailyThroughput(), + MonthlyThroughput = endpointData.ThroughputData.MonthlyThroughput(), MaxMonthlyThroughput = endpointData.ThroughputData.MaxMonthlyThroughput() }; diff --git a/src/Particular.LicensingComponent/ThroughputDataExtensions.cs b/src/Particular.LicensingComponent/ThroughputDataExtensions.cs index 901dc0ba66..33abbac65b 100644 --- a/src/Particular.LicensingComponent/ThroughputDataExtensions.cs +++ b/src/Particular.LicensingComponent/ThroughputDataExtensions.cs @@ -23,6 +23,11 @@ public static long MaxDailyThroughput(this List throughputs) return 0; } + public static MonthlyThroughput[] MonthlyThroughput(this List throughputs) => [.. throughputs + .SelectMany(data => data) + .GroupBy(kvp => $"{kvp.Key.Year}-{kvp.Key.Month.ToString().PadLeft(2, '0')}") + .Select(group => new MonthlyThroughput(group.Key, group.Sum(kvp => kvp.Value)))]; + public static long MaxMonthlyThroughput(this List throughputs) { var monthlySums = throughputs diff --git a/src/ServiceControl.Persistence.RavenDB/Throughput/LicensingDataStore.cs b/src/ServiceControl.Persistence.RavenDB/Throughput/LicensingDataStore.cs index d6455cb025..287ffb5a56 100644 --- a/src/ServiceControl.Persistence.RavenDB/Throughput/LicensingDataStore.cs +++ b/src/ServiceControl.Persistence.RavenDB/Throughput/LicensingDataStore.cs @@ -140,7 +140,7 @@ public async Task>> GetEndpointT .IncrementalTimeSeriesFor(document.GenerateDocumentId(), ThroughputTimeSeriesName) .GetAsync(from, token: cancellationToken); - if (results.TryGetValue(document.SanitizedName, out var throughputDatas) && + if (timeSeries is not null && results.TryGetValue(document.SanitizedName, out var throughputDatas) && throughputDatas is List throughputDataList) { var endpointDailyThroughputs = timeSeries.Select(entry => new EndpointDailyThroughput(DateOnly.FromDateTime(entry.Timestamp), (long)entry.Value));