-
-
Notifications
You must be signed in to change notification settings - Fork 77
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Muhammad Rehan Saeed
committed
Dec 9, 2019
1 parent
9427b43
commit fc0051f
Showing
5 changed files
with
135 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
48 changes: 48 additions & 0 deletions
48
Source/Boxed.AspNetCore/Middleware/ServerTimingMiddleware.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
namespace Boxed.AspNetCore.Middleware | ||
{ | ||
using System; | ||
using System.Diagnostics; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Http; | ||
|
||
/// <summary> | ||
/// Measures the time the request takes to process and returns this in a Server-Timing trailing HTTP header. It is | ||
/// used to surface any back-end server timing metrics (e.g. database read/write, CPU time, file system access, | ||
/// etc.) to the developer tools in the user's browser. | ||
/// </summary> | ||
/// <seealso cref="IMiddleware" /> | ||
public class ServerTimingMiddleware : IMiddleware | ||
{ | ||
private const string ServerTimingHttpHeader = "Server-Timing"; | ||
|
||
/// <inheritdoc/> | ||
public async Task InvokeAsync(HttpContext context, RequestDelegate next) | ||
{ | ||
if (context == null) | ||
{ | ||
throw new ArgumentNullException(nameof(context)); | ||
} | ||
|
||
if (next == null) | ||
{ | ||
throw new ArgumentNullException(nameof(next)); | ||
} | ||
|
||
if (context.Response.SupportsTrailers()) | ||
{ | ||
context.Response.DeclareTrailer(ServerTimingHttpHeader); | ||
var stopWatch = new Stopwatch(); | ||
stopWatch.Start(); | ||
|
||
await next(context).ConfigureAwait(false); | ||
|
||
stopWatch.Stop(); | ||
context.Response.AppendTrailer(ServerTimingHttpHeader, $"app;dur={stopWatch.ElapsedMilliseconds}.0"); | ||
} | ||
else | ||
{ | ||
await next(context).ConfigureAwait(false); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
57 changes: 57 additions & 0 deletions
57
Tests/Boxed.AspNetCore.Test/Middleware/ServerTimingMiddlewareTest.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
namespace Boxed.AspNetCore.Test.Middleware | ||
{ | ||
using System; | ||
using System.Threading.Tasks; | ||
using Boxed.AspNetCore.Middleware; | ||
using Microsoft.AspNetCore.Http; | ||
using Microsoft.AspNetCore.Http.Features; | ||
using Xunit; | ||
|
||
public class ServerTimingMiddlewareTest | ||
{ | ||
private readonly DefaultHttpContext context; | ||
private readonly RequestDelegate next; | ||
|
||
public ServerTimingMiddlewareTest() | ||
{ | ||
this.context = new DefaultHttpContext(); | ||
this.next = x => Task.CompletedTask; | ||
} | ||
|
||
[Fact] | ||
public void InvokeAsync_NullContext_ThrowsArgumentNullException() => | ||
Assert.ThrowsAsync<ArgumentNullException>(() => new ServerTimingMiddleware().InvokeAsync(null, this.next)); | ||
|
||
[Fact] | ||
public void InvokeAsync_NullNext_ThrowsArgumentNullException() => | ||
Assert.ThrowsAsync<ArgumentNullException>(() => new ServerTimingMiddleware().InvokeAsync(this.context, null)); | ||
|
||
[Fact] | ||
public async Task InvokeAsync_DoesntSupportTrailingHeaders_DontAddServerTimingHttpHeaderAsync() | ||
{ | ||
var responseTrailersFeature = this.context.Features.Get<IHttpResponseTrailersFeature>(); | ||
|
||
await new ServerTimingMiddleware().InvokeAsync(this.context, this.next).ConfigureAwait(false); | ||
|
||
Assert.Null(responseTrailersFeature); | ||
} | ||
|
||
[Fact] | ||
public async Task InvokeAsync_SupportsTrailingHeaders_AddsServerTimingHttpHeaderAsync() | ||
{ | ||
this.context.Features.Set<IHttpResponseTrailersFeature>(new ResponseTrailersFeature()); | ||
var responseTrailersFeature = this.context.Features.Get<IHttpResponseTrailersFeature>(); | ||
|
||
await new ServerTimingMiddleware().InvokeAsync(this.context, this.next).ConfigureAwait(false); | ||
|
||
var header = Assert.Single(responseTrailersFeature.Trailers); | ||
Assert.Equal("Server-Timing", header.Key); | ||
Assert.Equal("app;dur=0.0", header.Value.ToString()); | ||
} | ||
|
||
internal class ResponseTrailersFeature : IHttpResponseTrailersFeature | ||
{ | ||
public IHeaderDictionary Trailers { get; set; } = new HeaderDictionary(); | ||
} | ||
} | ||
} |
fc0051f
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need an
AddServerTimingMiddleware
extension to simplify registeringServerTimingMiddleware
forUseServerTiming
?fc0051f
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I missed that.