| File: Latency\ChecpointAcceptanceTests.cs | Web Access |
| Project: src\test\Libraries\Microsoft.AspNetCore.Diagnostics.Middleware.Tests\Microsoft.AspNetCore.Diagnostics.Middleware.Tests.csproj (Microsoft.AspNetCore.Diagnostics.Middleware.Tests) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Globalization; using System.Linq; using System.Net.Http; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Diagnostics.Latency; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting.Testing; using Microsoft.Extensions.Primitives; using Xunit; namespace Microsoft.AspNetCore.Diagnostics.Latency.Test; public class ChecpointAcceptanceTests { private static void SetupServices(IHostBuilder builder) { builder.ConfigureWebHost(webBuilder => webBuilder .UseTestServer() .ConfigureServices(services => RequestLatencyTelemetryServiceCollectionExtensions.AddRequestCheckpoint(services .AddRouting() .AddLatencyContext()) .AddScoped(p => p.GetRequiredService<ILatencyContextProvider>().CreateContext()))); } [Fact] public async Task RequestCheckpoint_CanMeasureMiddlewarePipeTime() { var reachedLambda = false; var exitPipelineValue = 0d; var responseProcessedValue = 0d; using var host = await FakeHost.CreateBuilder() .Configure(SetupServices) .ConfigureWebHost(webBuilder => webBuilder.Configure(app => { app.Use(async (context, next) => { var latencyContext = context.RequestServices.GetRequiredService<ILatencyContext>(); await next.Invoke().ConfigureAwait(false); latencyContext.TryGetCheckpoint(RequestCheckpointConstants.ElapsedTillPipelineExitMiddleware, out var exitPipeline, out var exitPipelineFreq); latencyContext.TryGetCheckpoint(RequestCheckpointConstants.ElapsedResponseProcessed, out var responseProcessed, out var responseProcessedFreq); reachedLambda = true; exitPipelineValue = ((double)exitPipeline / exitPipelineFreq) * 1000; responseProcessedValue = ((double)responseProcessed / responseProcessedFreq) * 1000; }); app.UseRouting(); app.UseRequestCheckpoint(); app.UseEndpoints(endpoints => endpoints.MapGet("/", async context => await context.Response.WriteAsync("Hello World!"))); })) .StartAsync(); _ = await host.GetTestClient().GetAsync("/"); Assert.True(reachedLambda); Assert.InRange(exitPipelineValue, 0, 10_000); Assert.InRange(responseProcessedValue, 0, 10_000); } [Fact] public async Task RequestCheckpointMiddleware_Does_Not_Throw_When_ServerTiming_Header_Is_Already_Set() { var exitPipelineValue = 0d; var responseProcessedValue = 0d; var alreadySetServerTimingHeader = new StringValues("Already-Set-Some-Header;blabla"); using var host = await FakeHost.CreateBuilder() .Configure(SetupServices) .ConfigureWebHost(webBuilder => webBuilder.Configure(app => { app.Use(async (context, next) => { var latencyContext = context.RequestServices.GetRequiredService<ILatencyContext>(); await next.Invoke().ConfigureAwait(false); latencyContext.TryGetCheckpoint(RequestCheckpointConstants.ElapsedTillPipelineExitMiddleware, out var exitPipeline, out var exitPipelineFreq); latencyContext.TryGetCheckpoint(RequestCheckpointConstants.ElapsedResponseProcessed, out var responseProcessed, out var responsedProcessedFreq); exitPipelineValue = ((double)exitPipeline / exitPipelineFreq) * 1000; responseProcessedValue = ((double)responseProcessed / responsedProcessedFreq) * 1000; }); app.Use((ctx, next) => { ctx.Response.Headers.Append("Server-Timing", alreadySetServerTimingHeader); return next(); }); app.UseRouting(); app.UseRequestCheckpoint(); app.UseEndpoints(endpoints => endpoints.MapGet("/", async context => await context.Response.WriteAsync("Hello World!"))); })) .StartAsync(); HttpResponseMessage? response = null; var e = await Record.ExceptionAsync(async () => response = await host.GetTestClient().GetAsync("/").ConfigureAwait(false)); Assert.Null(e); Assert.NotNull(response); var h = response.Headers .GetValues("Server-Timing") .FirstOrDefault(); Assert.NotNull(h); Assert.NotEmpty(h); Assert.Contains(alreadySetServerTimingHeader!, h); } [Fact] public async Task MiddlewareTest_ReturnsNotFoundForRequest() { using var host = await FakeHost.CreateBuilder() .Configure(SetupServices) .ConfigureWebHost(webBuilder => webBuilder.Configure(app => app.UseRequestCheckpoint())) .StartAsync(); using var response = await host.GetTestServer().CreateClient().GetAsync("/Path"); var timeHeaders = response.Headers.GetValues("Server-Timing").ToArray(); var metricFragments = Assert.Single(timeHeaders).Split('=', 2); Assert.Equal(2, metricFragments.Length); Assert.Equal("reqlatency;dur", metricFragments[0]); Assert.True(long.TryParse(metricFragments[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var value)); Assert.InRange(value, 0, 10_000); } }