From c349a55747747b3b2107ae8f4446612080986f9c Mon Sep 17 00:00:00 2001 From: Maksim Makushchenko Date: Sun, 5 May 2024 16:14:24 +0300 Subject: [PATCH] setup storing metrics in memory and serve by url --- .../ImageMetricsMiddleware.cs | 14 ------ Excursion360.Desktop/Program.cs | 17 +++++-- .../Services/IStateImagesMetricsStore.cs | 47 +++++++++++++++++++ ReleaseNotes.md | 7 ++- 4 files changed, 66 insertions(+), 19 deletions(-) delete mode 100644 Excursion360.Desktop/ImageMetricsMiddleware.cs create mode 100644 Excursion360.Desktop/Services/IStateImagesMetricsStore.cs diff --git a/Excursion360.Desktop/ImageMetricsMiddleware.cs b/Excursion360.Desktop/ImageMetricsMiddleware.cs deleted file mode 100644 index 9b01253..0000000 --- a/Excursion360.Desktop/ImageMetricsMiddleware.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Excursion360.Desktop; - -public class ImageMetricsMiddleware(RequestDelegate next, ILogger logger) -{ - public async Task InvokeAsync(HttpContext context) - { - var pathString = context.Request.Path.ToString(); - if (pathString.Contains("state_") && pathString.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase)) - { - logger.LogWarning("Hey! {Path}", pathString); - } - await next(context); - } -} diff --git a/Excursion360.Desktop/Program.cs b/Excursion360.Desktop/Program.cs index 0f46742..d54e3e7 100644 --- a/Excursion360.Desktop/Program.cs +++ b/Excursion360.Desktop/Program.cs @@ -11,8 +11,8 @@ Console.ForegroundColor = ConsoleColor.White; var builder = WebApplication.CreateBuilder(args); - builder.Logging.SetMinimumLevel(LogLevel.Information); +builder.Services.AddSingleton(); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { @@ -24,9 +24,15 @@ } var app = builder.Build(); -app.UseMiddleware(); var targetDirectory = GetExcursionDirectory(builder.Configuration.ExcursionDirectoryPath()); +app.MapGet("/eapi/preload.json", (IStateImagesMetricsStore stateImagesMetrics) => { + return new + { + images = stateImagesMetrics.MostPopularUrls(), + }; +}); + var fso = new FileServerOptions { FileProvider = new CompositeFileProvider( @@ -36,8 +42,11 @@ fso.DefaultFilesOptions.DefaultFileNames.Add("Resources/NotFound.html"); fso.StaticFileOptions.OnPrepareResponse = (context) => { - context.Context.Response.Headers.CacheControl = "no-cache, no-store"; - context.Context.Response.Headers.Expires = "-1"; + if (context.File.Name.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase) && context.File.PhysicalPath is not null) + { + var stateImagesMetricsStore = context.Context.RequestServices.GetRequiredService(); + stateImagesMetricsStore.IncrementImageHit(context.Context.Request.Path); + } }; app.UseFileServer(fso); diff --git a/Excursion360.Desktop/Services/IStateImagesMetricsStore.cs b/Excursion360.Desktop/Services/IStateImagesMetricsStore.cs new file mode 100644 index 0000000..ea6a1c6 --- /dev/null +++ b/Excursion360.Desktop/Services/IStateImagesMetricsStore.cs @@ -0,0 +1,47 @@ +using System.Collections.Concurrent; +using System.Text.Json; +using System.Text.RegularExpressions; + +namespace Excursion360.Desktop.Services; + +public interface IStateImagesMetricsStore +{ + void IncrementImageHit(string path); + string[] MostPopularUrls(); +} + +public partial class InMemoryIStateImagesMetricsStore : IStateImagesMetricsStore +{ + /// + /// Количества получений картинок по адресу. ключ = адрес картинки. Значение - количество получений. + /// + private readonly ConcurrentDictionary + hitCounts = new(); + private Regex stateAndImageRegex = GetStateAndImageRegex(); + public void IncrementImageHit(string path) + { + var match = stateAndImageRegex.Match(path); + if (!match.Success) + { + return; + } + hitCounts.AddOrUpdate(path, 1, (_, old) => old + 1); + Console.WriteLine(JsonSerializer.Serialize(hitCounts, new JsonSerializerOptions + { + WriteIndented = true, + })); + } + public string[] MostPopularUrls() + { + return hitCounts + .OrderByDescending(kvp => kvp.Value) + .ThenBy(kvp => kvp.Key) + .Select(kvp => kvp.Key) + .Take(10) + .ToArray(); + } + + [GeneratedRegex(@"state_.+[/\\].+\.jpg$")] + private static partial Regex GetStateAndImageRegex(); + +} diff --git a/ReleaseNotes.md b/ReleaseNotes.md index 24e213d..5eca5c7 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -1 +1,6 @@ -# Возможность выбирать используемый браузер из установленных на ПК +- `v4.0` + - Обновлен .NET/Nuke до 8, убраны все предупреждения + - Обновлена структура проекта до последней версии ASP.NET Core + - Базовая папка для выбора экскурсий может выбираться через `--excursionsPath путь_к_папке` + - Добавлена обработка `/eapi/preload.json`, по которому будут отдаваться адреса изображений, которые чаще всего просматриваются +- `v3.0` Возможность выбирать используемый браузер из установленных на ПК