diff --git a/docs/release-notes.md b/docs/release-notes.md index 7a052af99..828ef200e 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -47,6 +47,9 @@ * `CustomLocations` entries which use the new [unique string ID](https://stardewvalleywiki.com/Modding:Common_data_field_types#Unique_string_ID) format; * `AddWarps` warps when a location name contains a dot. +* For the web API: + * The [anonymized metrics for update check requests](technical/web.md#modsmetrics) now counts requests by SMAPI and game version. + ## 4.0.8 Released 21 April 2024 for Stardew Valley 1.6.4 or later. @@ -165,6 +168,7 @@ Released 19 March 2024 for Stardew Valley 1.6.0 or later. See [release highlight * For the web UI: * Updated JSON validator for Content Patcher 2.0.0. + * Added [anonymized metrics for update check requests](technical/web.md#modsmetrics). * Fixed uploaded log/JSON file expiry alway shown as renewed. * Fixed update check for mods with a prerelease version tag not recognized by the ModDrop API. SMAPI now parses the version itself if needed. diff --git a/docs/technical/web.md b/docs/technical/web.md index fefe15353..4b99436b7 100644 --- a/docs/technical/web.md +++ b/docs/technical/web.md @@ -189,7 +189,7 @@ may be useful to external tools. Example request: ```js -POST https://smapi.io/api/v3.0/mods +POST https://smapi.io/api/v4.0.0/mods { "mods": [ { @@ -199,8 +199,8 @@ POST https://smapi.io/api/v3.0/mods "isBroken": false } ], - "apiVersion": "3.0.0", - "gameVersion": "1.4.0", + "apiVersion": "4.0.0", + "gameVersion": "1.6.9", "platform": "Windows", "includeExtendedMetadata": true } @@ -329,7 +329,7 @@ deployed or restarted. Example request: ```js -GET https://smapi.io/api/v3.0/mods/metrics +GET https://smapi.io/api/v4.0.0/mods/metrics ``` ## Short URLs diff --git a/src/SMAPI.Web/Controllers/ModsApiController.cs b/src/SMAPI.Web/Controllers/ModsApiController.cs index 64c95dacf..844c7efba 100644 --- a/src/SMAPI.Web/Controllers/ModsApiController.cs +++ b/src/SMAPI.Web/Controllers/ModsApiController.cs @@ -83,7 +83,7 @@ public ModsApiController(IWebHostEnvironment environment, IWikiCacheRepository w public async Task> PostAsync([FromBody] ModSearchModel? model, [FromRoute] string version) { ApiMetricsModel metrics = MetricsManager.GetMetricsForNow(); - metrics.TrackRequest(); + metrics.TrackRequest(model?.ApiVersion, model?.GameVersion); if (model?.Mods == null) return Array.Empty(); diff --git a/src/SMAPI.Web/Framework/Metrics/ApiMetricsModel.cs b/src/SMAPI.Web/Framework/Metrics/ApiMetricsModel.cs index e3d68c806..310b9d335 100644 --- a/src/SMAPI.Web/Framework/Metrics/ApiMetricsModel.cs +++ b/src/SMAPI.Web/Framework/Metrics/ApiMetricsModel.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using StardewModdingAPI.Toolkit.Framework.UpdateData; @@ -15,14 +16,28 @@ internal class ApiMetricsModel /// The metrics by mod site. public Dictionary Sites { get; } = new(); + /// The number of update-check requests by SMAPI version. + public Dictionary ByApiVersion { get; } = new(StringComparer.OrdinalIgnoreCase); + + /// The number of update-check requests by game version. + public Dictionary ByGameVersion { get; } = new(StringComparer.OrdinalIgnoreCase); + /********* ** Public methods *********/ /// Track an update-check request received by the API. - public void TrackRequest() + /// The SMAPI version installed by the player. + /// The game version installed by the player. + public void TrackRequest(ISemanticVersion? apiVersion, ISemanticVersion? gameVersion) { this.ApiRequests++; + + string apiVersionStr = apiVersion?.ToString() ?? ""; + string gameVersionStr = gameVersion?.ToString() ?? ""; + + this.ByApiVersion[apiVersionStr] = this.ByApiVersion.GetValueOrDefault(apiVersionStr) + 1; + this.ByGameVersion[gameVersionStr] = this.ByGameVersion.GetValueOrDefault(gameVersionStr) + 1; } /// Track the update-check result for a specific update key. diff --git a/src/SMAPI.Web/Framework/Metrics/MetricsManager.cs b/src/SMAPI.Web/Framework/Metrics/MetricsManager.cs index 0189e12e1..1dc32391f 100644 --- a/src/SMAPI.Web/Framework/Metrics/MetricsManager.cs +++ b/src/SMAPI.Web/Framework/Metrics/MetricsManager.cs @@ -47,6 +47,8 @@ public static MetricsSummary GetSummary(ModUpdateCheckConfig config) var totals = new MetricsModel(); var bySite = new Dictionary(); var byDate = new Dictionary(); + var byApiVersion = new Dictionary(StringComparer.OrdinalIgnoreCase); + var byGameVersion = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach ((string hourlyKey, ApiMetricsModel hourly) in MetricsManager.Metrics) { // totals @@ -68,6 +70,12 @@ public static MetricsSummary GetSummary(ModUpdateCheckConfig config) if (!byDate.TryGetValue(dailyKey, out ApiMetricsModel? daily)) byDate[dailyKey] = daily = new ApiMetricsModel(); + // by version + foreach ((string apiVersion, long count) in hourly.ByApiVersion) + byApiVersion[apiVersion] = byApiVersion.GetValueOrDefault(apiVersion) + count; + foreach ((string gameVersion, long count) in hourly.ByGameVersion) + byGameVersion[gameVersion] = byGameVersion.GetValueOrDefault(gameVersion) + count; + daily.AggregateFrom(hourly); } @@ -80,6 +88,8 @@ public static MetricsSummary GetSummary(ModUpdateCheckConfig config) TotalCacheHits: totals.CacheHits, TotalSuccessCacheMisses: totals.SuccessCacheMisses, TotalErrorCacheMisses: totals.ErrorCacheMisses, + ByApiVersion: byApiVersion, + ByGameVersion: byGameVersion, BySite: bySite, ByDate: byDate ); diff --git a/src/SMAPI.Web/Framework/Metrics/MetricsSummary.cs b/src/SMAPI.Web/Framework/Metrics/MetricsSummary.cs index 847b88049..954bb3067 100644 --- a/src/SMAPI.Web/Framework/Metrics/MetricsSummary.cs +++ b/src/SMAPI.Web/Framework/Metrics/MetricsSummary.cs @@ -13,6 +13,8 @@ namespace StardewModdingAPI.Web.Framework.Metrics /// The number of times an update key returned data from the cache. /// The number of times an update key successfully fetched data from a remote mod site. /// The number of times an update key could not fetch data from a remote mod site (e.g. mod page didn't exist or mod site returned an API error). + /// The number of update-check request by SMAPI version. + /// The number of update-check request by game version. /// The metrics grouped by site. /// The metrics grouped by UTC date. internal record MetricsSummary( @@ -24,6 +26,8 @@ internal record MetricsSummary( int TotalCacheHits, int TotalSuccessCacheMisses, int TotalErrorCacheMisses, + IDictionary ByApiVersion, + IDictionary ByGameVersion, IDictionary BySite, IDictionary ByDate );