diff --git a/DebugProbe.AspNetCore/Extensions/DebugProbeExtensions.cs b/DebugProbe.AspNetCore/Extensions/DebugProbeExtensions.cs index 23f6c2f..3681298 100644 --- a/DebugProbe.AspNetCore/Extensions/DebugProbeExtensions.cs +++ b/DebugProbe.AspNetCore/Extensions/DebugProbeExtensions.cs @@ -30,6 +30,7 @@ public static IServiceCollection AddDebugProbe( public static IApplicationBuilder UseDebugProbe(this IApplicationBuilder app) { app.UseMiddleware(); + app.ApplicationServices.GetRequiredService(); if (app is WebApplication webApp) { @@ -59,59 +60,83 @@ public static IApplicationBuilder UseDebugProbe(this IApplicationBuilder app) var prettyRequest = JsonUtils.Format(item.RequestBody); var prettyResponse = JsonUtils.Format(item.ResponseBody); - var html = HtmlRenderer.RenderDetailsPage(item, prettyRequest, prettyResponse); + var html = HtmlRenderer.RenderDetailsPage(item, store.Environment, prettyRequest, prettyResponse); ctx.Response.ContentType = "text/html"; await ctx.Response.WriteAsync(html); }).ExcludeFromDescription(); - webApp.MapGet("/debug/compare/{id}", async (string id, string url, DebugEntryStore store) => + webApp.MapGet("/debug/compare/{id}", async (string id, string baseUrl, string remoteTraceId, DebugEntryStore store) => { - var local = store.Get(id); - if (local is null) + var localEnvironment = store.Environment; + var localEntry = store.Get(id); + if (localEntry is null) { return Results.NotFound("Local trace not found"); } - DebugEntry? remote; + + var normalizedBaseUrl = baseUrl.TrimEnd('/'); + + var remoteEnvironmentUrl = + $"{normalizedBaseUrl}/debug/environment"; + + var remoteEntryUrl = + $"{normalizedBaseUrl}/debug/json/{remoteTraceId}"; + + DebugEntry? remoteEntry; + DebugEnvironment? remoteEnvironment; try { - remote = await Http.GetFromJsonAsync(url); + remoteEnvironment = await Http.GetFromJsonAsync(remoteEnvironmentUrl); + + if (remoteEnvironment is null) + { + return Results.BadRequest("Failed to load remote environment"); + } + + remoteEntry = await Http.GetFromJsonAsync(remoteEntryUrl); + + if (remoteEntry is null) + { + return Results.NotFound("Remote trace not found"); + } } catch { return Results.BadRequest("Failed to reach remote server"); } - if (remote is null) - { - return Results.NotFound("Remote trace not found"); - } - - var diff = DebugEntryComparer.Compare(local, remote); + + var diff = DebugEntryComparer.Compare(localEntry, remoteEntry); return Results.Ok(new { - method = new { local = local.Method, remote = remote.Method }, - path = new { local = local.Path, remote = remote.Path }, - status = new { local = local.StatusCode, remote = remote.StatusCode }, + method = new { local = localEntry.Method, remote = remoteEntry.Method }, + path = new { local = localEntry.Path, remote = remoteEntry.Path }, + status = new { local = localEntry.StatusCode, remote = remoteEntry.StatusCode }, requestTime = new { - local = local.RequestTimeUtc.ToLocalTime().ToString("HH:mm:ss"), - remote = remote.RequestTimeUtc.ToLocalTime().ToString("HH:mm:ss"), + local = localEntry.RequestTimeUtc.ToLocalTime().ToString("HH:mm:ss"), + remote = remoteEntry.RequestTimeUtc.ToLocalTime().ToString("HH:mm:ss"), }, - environment = new { local = local.Environment, remote = remote.Environment }, - culture = new { local = local.Culture, remote = remote.Culture }, - requestBody = new { local = local.RequestBody ?? "", remote = remote.RequestBody ?? "" }, - responseBody = new { local = local.ResponseBody ?? "", remote = remote.ResponseBody ?? "" }, + environment = new { local = localEnvironment.Environment, remote = remoteEnvironment?.Environment ?? "" }, + culture = new { local = localEnvironment.Culture, remote = remoteEnvironment?.Culture ?? "" }, + requestBody = new { local = localEntry.RequestBody ?? "", remote = remoteEntry.RequestBody ?? "" }, + responseBody = new { local = localEntry.ResponseBody ?? "", remote = remoteEntry.ResponseBody ?? "" }, diffs = diff }); }).ExcludeFromDescription(); + webApp.MapGet("/debug/environment", (DebugEntryStore store) => + { + return Results.Ok(store.Environment); + }).ExcludeFromDescription(); + webApp.MapGet("/debug/json/{id}", (string id, DebugEntryStore store) => { var item = store.Get(id); diff --git a/DebugProbe.AspNetCore/Internal/DebugEntryComparer.cs b/DebugProbe.AspNetCore/Internal/DebugEntryComparer.cs index c136ebe..2149471 100644 --- a/DebugProbe.AspNetCore/Internal/DebugEntryComparer.cs +++ b/DebugProbe.AspNetCore/Internal/DebugEntryComparer.cs @@ -19,12 +19,6 @@ public static List Compare(DebugEntry a, DebugEntry b) if (a.StatusCode != b.StatusCode) AddDiff(diffs, "Status", a.StatusCode, b.StatusCode, "meta"); - if (a.Environment != b.Environment) - AddDiff(diffs, "Environment", a.Environment, b.Environment, "meta"); - - if (a.Culture != b.Culture) - AddDiff(diffs, "Culture", a.Culture, b.Culture, "meta"); - CompareBody(a.RequestBody, b.RequestBody, RequestBodyPath, diffs); CompareBody(a.ResponseBody, b.ResponseBody, ResponseBodyPath, diffs); diff --git a/DebugProbe.AspNetCore/Internal/HtmlRenderer.cs b/DebugProbe.AspNetCore/Internal/HtmlRenderer.cs index 5d74a4a..c388143 100644 --- a/DebugProbe.AspNetCore/Internal/HtmlRenderer.cs +++ b/DebugProbe.AspNetCore/Internal/HtmlRenderer.cs @@ -39,7 +39,7 @@ public static string RenderIndexPage(List items) return BuildLayout(EmbeddedResources.Index.Replace("{{rows}}", rows)); } - public static string RenderDetailsPage(DebugEntry x, string req, string res) + public static string RenderDetailsPage(DebugEntry x, DebugEnvironment e, string req, string res) { var headers = string.Join("", x.Headers.Select(h => $"{Encode(h.Key)}{Encode(h.Value)}")); @@ -71,14 +71,14 @@ public static string RenderDetailsPage(DebugEntry x, string req, string res) .Replace("{{requestSize}}", x.RequestSize.ToString()) .Replace("{{responseSize}}", x.ResponseSize.ToString()) - .Replace("{{env}}", Encode(x.Environment)) - .Replace("{{culture}}", Encode(x.Culture)) + .Replace("{{env}}", Encode(e.Environment)) + .Replace("{{culture}}", Encode(e.Culture)) - .Replace("{{machineName}}", Encode(x.MachineName)) - .Replace("{{timeZone}}", Encode(x.TimeZone)) - .Replace("{{decimalSeparator}}", Encode(x.DecimalSeparator)) - .Replace("{{dateFormat}}", x.DateFormat ?? "") - .Replace("{{assemblyVersion}}", Encode(x.AssemblyVersion)) + .Replace("{{machineName}}", Encode(e.MachineName)) + .Replace("{{timeZone}}", Encode(e.TimeZone)) + .Replace("{{decimalSeparator}}", Encode(e.DecimalSeparator)) + .Replace("{{dateFormat}}", e.DateFormat ?? "") + .Replace("{{assemblyVersion}}", Encode(e.AssemblyVersion)) .Replace("{{requestUrl}}", Encode(string.IsNullOrEmpty(x.RequestUrl) ? "(empty)" : x.RequestUrl)) .Replace("{{request}}", Encode(string.IsNullOrEmpty(req) ? "(empty)" : req)) diff --git a/DebugProbe.AspNetCore/Middleware/DebugProbeMiddleware.cs b/DebugProbe.AspNetCore/Middleware/DebugProbeMiddleware.cs index dae83f7..4f1cec3 100644 --- a/DebugProbe.AspNetCore/Middleware/DebugProbeMiddleware.cs +++ b/DebugProbe.AspNetCore/Middleware/DebugProbeMiddleware.cs @@ -1,13 +1,9 @@ using System.Diagnostics; -using System.Globalization; -using System.Reflection; using System.Text; -using DebugProbe.AspNetCore.Internal; using DebugProbe.AspNetCore.Models; using DebugProbe.AspNetCore.Options; using DebugProbe.AspNetCore.Storage; using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Options; namespace DebugProbe.AspNetCore.Middleware; @@ -83,25 +79,12 @@ public async Task Invoke(HttpContext context, DebugEntryStore store) await ms.CopyToAsync(originalBody); context.Response.Body = originalBody; - var shortDatePattern = CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern; - var index = shortDatePattern.LastIndexOf('y'); - var dataFormat = index >= 0 ? shortDatePattern[..(index + 1)] : shortDatePattern; - var statusCode = exception && context.Response.StatusCode == 200 ? 500 : context.Response.StatusCode; store.Add(new DebugEntry { Id = Guid.NewGuid().ToString(), - // Environment - Environment = EnvironmentUtils.TryGetEnvironment(), - MachineName = Environment.MachineName, - AssemblyVersion = Assembly.GetEntryAssembly()?.GetName().Version?.ToString(), - TimeZone = TimeZoneInfo.Local.DisplayName, - Culture = CultureInfo.CurrentCulture.Name, - DecimalSeparator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator, - DateFormat = dataFormat, - // Overview Method = context.Request.Method, Path = context.Request.Path, diff --git a/DebugProbe.AspNetCore/Models/DebugEntry.cs b/DebugProbe.AspNetCore/Models/DebugEntry.cs index 05d18c8..fa7fe93 100644 --- a/DebugProbe.AspNetCore/Models/DebugEntry.cs +++ b/DebugProbe.AspNetCore/Models/DebugEntry.cs @@ -19,17 +19,6 @@ public class DebugEntry public long ResponseSize { get; set; } public string ResponseBody { get; set; } = default!; - // Environment - public string Environment { get; set; } = default!; - public string Culture { get; set; } = default!; - public string? UiCulture { get; set; } - - public string? MachineName { get; set; } - public string? AssemblyVersion { get; set; } - public string? TimeZone { get; set; } - public string? DecimalSeparator { get; set; } - public string? DateFormat { get; set; } - // Headers public Dictionary Headers { get; set; } = new(); diff --git a/DebugProbe.AspNetCore/Models/DebugEnvironment.cs b/DebugProbe.AspNetCore/Models/DebugEnvironment.cs new file mode 100644 index 0000000..bd2d762 --- /dev/null +++ b/DebugProbe.AspNetCore/Models/DebugEnvironment.cs @@ -0,0 +1,13 @@ +namespace DebugProbe.AspNetCore.Models; + +public class DebugEnvironment +{ + public string Environment { get; init; } = default!; + public string Culture { get; init; } = default!; + public string? UiCulture { get; init; } + public string? MachineName { get; init; } + public string? AssemblyVersion { get; init; } + public string? TimeZone { get; init; } + public string? DecimalSeparator { get; init; } + public string? DateFormat { get; init; } +} diff --git a/DebugProbe.AspNetCore/Resources/js/debugprobe-compare.js b/DebugProbe.AspNetCore/Resources/js/debugprobe-compare.js index 1db7772..f544fd5 100644 --- a/DebugProbe.AspNetCore/Resources/js/debugprobe-compare.js +++ b/DebugProbe.AspNetCore/Resources/js/debugprobe-compare.js @@ -11,8 +11,7 @@ setCompareResult('Comparing...'); try { - const remoteUrl = `${base.replace(/\/$/, '')}/debug/json/${remoteId}`; - const res = await fetch(`/debug/compare/${id}?url=${encodeURIComponent(remoteUrl)}`); + const res = await fetch(`/debug/compare/${id}?baseUrl=${encodeURIComponent(base)}&remoteTraceId=${encodeURIComponent(remoteId)}`); if (!res.ok) { const text = await res.json(); diff --git a/DebugProbe.AspNetCore/Storage/DebugEntryStore.cs b/DebugProbe.AspNetCore/Storage/DebugEntryStore.cs index 2402104..6a3ae3a 100644 --- a/DebugProbe.AspNetCore/Storage/DebugEntryStore.cs +++ b/DebugProbe.AspNetCore/Storage/DebugEntryStore.cs @@ -1,4 +1,7 @@ using System.Collections.Concurrent; +using System.Globalization; +using System.Reflection; +using DebugProbe.AspNetCore.Internal; using DebugProbe.AspNetCore.Models; using DebugProbe.AspNetCore.Options; @@ -9,12 +12,26 @@ namespace DebugProbe.AspNetCore.Storage; /// public class DebugEntryStore { + public DebugEnvironment Environment { get; } + private readonly ConcurrentQueue _queue = new(); private readonly int _limit; public DebugEntryStore(DebugProbeOptions options) { _limit = options.MaxEntries; + + Environment = new DebugEnvironment + { + Environment = EnvironmentUtils.TryGetEnvironment(), + MachineName = System.Environment.MachineName, + AssemblyVersion = Assembly.GetEntryAssembly()?.GetName().Version?.ToString(), + TimeZone = TimeZoneInfo.Local.DisplayName, + Culture = CultureInfo.CurrentCulture.Name, + UiCulture = CultureInfo.CurrentUICulture.Name, + DecimalSeparator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator, + DateFormat = GetDateFormat() + }; } public void Add(DebugEntry entry) @@ -38,4 +55,13 @@ public void Clear() { while (_queue.TryDequeue(out _)) { } } + + private string GetDateFormat() + { + var shortDatePattern = CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern; + var index = shortDatePattern.LastIndexOf('y'); + var dataFormat = index >= 0 ? shortDatePattern[..(index + 1)] : shortDatePattern; + + return dataFormat; + } } \ No newline at end of file