diff --git a/src/Microsoft.ApplicationInsights.AspNet/Extensions/HttpRequestExtensions.cs b/src/Microsoft.ApplicationInsights.AspNet/Extensions/HttpRequestExtensions.cs new file mode 100644 index 0000000..fcbefae --- /dev/null +++ b/src/Microsoft.ApplicationInsights.AspNet/Extensions/HttpRequestExtensions.cs @@ -0,0 +1,53 @@ +namespace Microsoft.ApplicationInsights.AspNet.Extensions +{ + using Microsoft.AspNet.Http; + using System; + using System.Text; + + /// + /// Set of extension methods for Microsoft.AspNet.Http.HttpRequest + /// + public static class HttpRequestExtensions + { + /// + /// Gets http request Uri from request object + /// + /// request + /// A New Uri object representing request Uri + public static Uri GetUri(this HttpRequest request) + { + if (null == request) + { + throw new ArgumentNullException("request"); + } + + if (true == string.IsNullOrWhiteSpace(request.Scheme)) + { + throw new ArgumentException("Http request Scheme is not specified"); + } + + if (false == request.Host.HasValue) + { + throw new ArgumentException("Http request Host is not specified"); + } + + var builder = new StringBuilder(); + + builder.Append(request.Scheme) + .Append("://") + .Append(request.Host); + + if (true == request.Path.HasValue) + { + builder.Append(request.Path.Value); + } + + if (true == request.QueryString.HasValue) + { + builder.Append(request.QueryString); + } + + return new Uri(builder.ToString()); + } + } +} diff --git a/src/Microsoft.ApplicationInsights.AspNet/RequestTrackingMiddleware.cs b/src/Microsoft.ApplicationInsights.AspNet/RequestTrackingMiddleware.cs index 4235bb1..39f5560 100644 --- a/src/Microsoft.ApplicationInsights.AspNet/RequestTrackingMiddleware.cs +++ b/src/Microsoft.ApplicationInsights.AspNet/RequestTrackingMiddleware.cs @@ -11,6 +11,8 @@ using Microsoft.AspNet.Http; using Microsoft.Framework.DependencyInjection; using Microsoft.ApplicationInsights.Extensibility.Implementation; + using Microsoft.ApplicationInsights.AspNet.Extensions; + /// /// Sends telemetry about requests handled by the application to the Microsoft Application Insights service. @@ -50,6 +52,7 @@ telemetry.ResponseCode = httpContext.Response.StatusCode.ToString(); telemetry.Success = httpContext.Response.StatusCode < 400; telemetry.HttpMethod = httpContext.Request.Method; + telemetry.Url = httpContext.Request.GetUri(); telemetry.Context.GetInternalContext().SdkVersion = this.sdkVersion; this.telemetryClient.TrackRequest(telemetry); diff --git a/test/FunctionalTestUtils/project.json b/test/FunctionalTestUtils/project.json index b1d70d3..e3bfb65 100644 --- a/test/FunctionalTestUtils/project.json +++ b/test/FunctionalTestUtils/project.json @@ -8,7 +8,7 @@ "Microsoft.AspNet.Server.WebListener": "1.0.0-beta4", "Microsoft.Framework.Runtime": "1.0.0-beta4", "Microsoft.Net.Http.Client": "1.0.0-*", - "xunit": "2.0.0-beta4-build2738" + "xunit": "2.1.0-beta2-*" }, "frameworks": { diff --git a/test/Microsoft.ApplicationInsights.AspNet.Tests/Extensions/HttpRequestExtensionsTest.cs b/test/Microsoft.ApplicationInsights.AspNet.Tests/Extensions/HttpRequestExtensionsTest.cs new file mode 100644 index 0000000..72e4f56 --- /dev/null +++ b/test/Microsoft.ApplicationInsights.AspNet.Tests/Extensions/HttpRequestExtensionsTest.cs @@ -0,0 +1,106 @@ +namespace Microsoft.ApplicationInsights.AspNet.Tests.Extensions +{ + using Microsoft.ApplicationInsights.AspNet.Extensions; + using Microsoft.AspNet.Http; + using Microsoft.AspNet.Http.Core; + using System; + using Xunit; + + public class HttpRequestExtensionsTest + { + const string ExpectedSchema = "http"; + const string ExpectedHostName = "randomhost"; + const string ExpectedPath = "/path/path/"; + const string ExpectedQueryString = "?queryType=1"; + + [Fact] + public void TestGetUriThrowsExceptionOnNullRequestObject() + { + Assert.Throws( + typeof(ArgumentNullException), + () => + { + HttpRequestExtensions.GetUri(null); + }); + } + + [Fact] + public void TestGetUriThrowsExceptionOnRequestObjectSchemeIsEmpty() + { + var request = new DefaultHttpContext().Request; + + var exception = Assert.Throws( + typeof(ArgumentException), + () => + { + HttpRequestExtensions.GetUri(request); + }); + + Assert.True(exception.Message.Contains("Scheme"), "Scheme is not mentioned in the exception"); + } + + [Fact] + public void TestGetUriThrowsExceptionOnRequestObjectHostIsNotSpecified() + { + var request = new DefaultHttpContext().Request; + request.Scheme = ExpectedSchema; + + var exception = Assert.Throws( + typeof(ArgumentException), + () => + { + HttpRequestExtensions.GetUri(request); + }); + + Assert.True(exception.Message.Contains("Host"), "Host is not mentioned in the exception"); + } + + [Fact] + public void TestGetUriReturnsCorrectUriIfRequestObjectSchemeAndHostAreSpecified() + { + var request = new DefaultHttpContext().Request; + + request.Scheme = ExpectedSchema; + request.Host = new HostString(ExpectedHostName); + + var uri = HttpRequestExtensions.GetUri(request); + + Assert.Equal( + new Uri(string.Format("{0}://{1}", ExpectedSchema, ExpectedHostName)), + uri); + } + + [Fact] + public void TestGetUriReturnsCorrectUriIfRequestObjectSchemeAndHostAndPathAreSpecified() + { + var request = new DefaultHttpContext().Request; + + request.Scheme = ExpectedSchema; + request.Host = new HostString(ExpectedHostName); + request.Path = new PathString(ExpectedPath); + + var uri = HttpRequestExtensions.GetUri(request); + + Assert.Equal( + new Uri(string.Format("{0}://{1}{2}", ExpectedSchema, ExpectedHostName, ExpectedPath)), + uri); + } + + [Fact] + public void TestGetUriReturnsCorrectUriIfRequestObjectSchemeAndHostAndPathAndQueryStringAreSpecified() + { + var request = new DefaultHttpContext().Request; + + request.Scheme = ExpectedSchema; + request.Host = new HostString(ExpectedHostName); + request.Path = new PathString(ExpectedPath); + request.QueryString = new QueryString(ExpectedQueryString); + + var uri = HttpRequestExtensions.GetUri(request); + + Assert.Equal( + new Uri(string.Format("{0}://{1}{2}{3}", ExpectedSchema, ExpectedHostName, ExpectedPath, ExpectedQueryString)), + uri); + } + } +} \ No newline at end of file diff --git a/test/Microsoft.ApplicationInsights.AspNet.Tests/RequestTrackingMiddlewareTest.cs b/test/Microsoft.ApplicationInsights.AspNet.Tests/RequestTrackingMiddlewareTest.cs index 1949d88..90f7336 100644 --- a/test/Microsoft.ApplicationInsights.AspNet.Tests/RequestTrackingMiddlewareTest.cs +++ b/test/Microsoft.ApplicationInsights.AspNet.Tests/RequestTrackingMiddlewareTest.cs @@ -8,24 +8,64 @@ using Microsoft.AspNet.Builder; using Microsoft.AspNet.Http.Core; using Xunit; + using Microsoft.AspNet.Http; + using System; public class RequestTrackingMiddlewareTest { + private const string HttpRequestScheme = "http"; + private readonly HostString httpRequestHost = new HostString("testHost"); + private readonly PathString httpRequestPath = new PathString("/path/path"); + private readonly QueryString httpRequestQueryString = new QueryString("?query=1"); + + private const string ExpectedSdkVersion = "aspnet5"; + private ITelemetry sentTelemetry; - [Fact] - public async Task SdkVersionIsPopulatedByMiddleware() + private readonly RequestDelegate nextMiddleware = async httpContext => { + httpContext.Response.StatusCode = 200; + await httpContext.Response.Body.WriteAsync(new byte[0], 0, 0); + }; + + private readonly RequestTrackingMiddleware middleware; + + public RequestTrackingMiddlewareTest() { - RequestDelegate nextMiddleware = async httpContext => { - httpContext.Response.StatusCode = 200; - await httpContext.Response.Body.WriteAsync(new byte[0], 0, 0); - }; - var middleware = new RequestTrackingMiddleware(nextMiddleware, CommonMocks.MockTelemetryClient(telemetry => this.sentTelemetry = telemetry)); + this.middleware = new RequestTrackingMiddleware( + this.nextMiddleware, + CommonMocks.MockTelemetryClient(telemetry => this.sentTelemetry = telemetry)); + } - await middleware.Invoke(new DefaultHttpContext(), new RequestTelemetry()); + [Fact] + public async Task TestSdkVersionIsPopulatedByMiddleware() + { + var context = new DefaultHttpContext(); + context.Request.Scheme = HttpRequestScheme; + context.Request.Host = this.httpRequestHost; - Assert.NotEmpty(sentTelemetry.Context.GetInternalContext().SdkVersion); - Assert.Contains("aspnet5", sentTelemetry.Context.GetInternalContext().SdkVersion); + await middleware.Invoke(context, new RequestTelemetry()); + + Assert.NotEmpty(this.sentTelemetry.Context.GetInternalContext().SdkVersion); + Assert.Contains(ExpectedSdkVersion, this.sentTelemetry.Context.GetInternalContext().SdkVersion); + } + + [Fact] + public async Task TestRequestUriIsPopulatedByMiddleware() + { + var context = new DefaultHttpContext(); + context.Request.Scheme = HttpRequestScheme; + context.Request.Host = this.httpRequestHost; + context.Request.Path = this.httpRequestPath; + context.Request.QueryString = this.httpRequestQueryString; + + var telemetry = new RequestTelemetry(); + await middleware.Invoke(context, telemetry); + + Assert.NotNull(telemetry.Url); + + Assert.Equal( + new Uri(string.Format("{0}://{1}{2}{3}", HttpRequestScheme, httpRequestHost.Value, httpRequestPath.Value, httpRequestQueryString.Value)), + telemetry.Url); } } } diff --git a/test/Microsoft.ApplicationInsights.AspNet.Tests/project.json b/test/Microsoft.ApplicationInsights.AspNet.Tests/project.json index bbcd6cc..f7588ab 100644 --- a/test/Microsoft.ApplicationInsights.AspNet.Tests/project.json +++ b/test/Microsoft.ApplicationInsights.AspNet.Tests/project.json @@ -8,10 +8,11 @@ "Microsoft.AspNet.Mvc.Core": "6.0.0-beta4-*", "Microsoft.Framework.Logging": "1.0.0-beta4-*", "Microsoft.Framework.ConfigurationModel.Json": "1.0.0-beta4-*", - "xunit.runner.aspnet": "2.0.0-aspnet-beta4-*" + "xunit": "2.1.0-beta2-*", + "xunit.runner.dnx": "2.1.0-beta2-*" }, "commands": { - "test": "xunit.runner.aspnet" + "test": "xunit.runner.dnx" }, "frameworks": { "dnx451": { diff --git a/test/Mvc6Framework45.FunctionalTests/FunctionalTest/RequestTelemetryTests.cs b/test/Mvc6Framework45.FunctionalTests/FunctionalTest/RequestTelemetryTests.cs index 6ff5ecf..8fc36d3 100644 --- a/test/Mvc6Framework45.FunctionalTests/FunctionalTest/RequestTelemetryTests.cs +++ b/test/Mvc6Framework45.FunctionalTests/FunctionalTest/RequestTelemetryTests.cs @@ -13,39 +13,46 @@ [Fact] public void TestBasicRequestPropertiesAfterRequestingHomeController() { + const string RequestPath = "/"; + var expectedRequestTelemetry = new RequestTelemetry(); expectedRequestTelemetry.HttpMethod = "GET"; expectedRequestTelemetry.Name = "GET Home/Index"; expectedRequestTelemetry.ResponseCode = "200"; expectedRequestTelemetry.Success = true; - // expectedRequestTelemetry.Url ??? + expectedRequestTelemetry.Url = new System.Uri(this.Server.BaseHost + RequestPath); - this.ValidateBasicRequest("/", expectedRequestTelemetry); + this.ValidateBasicRequest(RequestPath, expectedRequestTelemetry); } [Fact] public void TestBasicRequestPropertiesAfterRequestingActionWithParameter() { + const string RequestPath = "/Home/About/5"; + var expectedRequestTelemetry = new RequestTelemetry(); expectedRequestTelemetry.HttpMethod = "GET"; expectedRequestTelemetry.Name = "GET Home/About [id]"; expectedRequestTelemetry.ResponseCode = "200"; expectedRequestTelemetry.Success = true; - // expectedRequestTelemetry.Url ??? + expectedRequestTelemetry.Url = new System.Uri(this.Server.BaseHost + RequestPath); - this.ValidateBasicRequest("/Home/About/5", expectedRequestTelemetry); + this.ValidateBasicRequest(RequestPath, expectedRequestTelemetry); } [Fact] public void TestBasicRequestPropertiesAfterRequestingNotExistingController() { + const string RequestPath = "/not/existing/controller"; + var expectedRequestTelemetry = new RequestTelemetry(); expectedRequestTelemetry.HttpMethod = "GET"; expectedRequestTelemetry.Name = "GET /not/existing/controller"; expectedRequestTelemetry.ResponseCode = "404"; expectedRequestTelemetry.Success = false; + expectedRequestTelemetry.Url = new System.Uri(this.Server.BaseHost + RequestPath); - this.ValidateBasicRequest("/not/existing/controller", expectedRequestTelemetry); + this.ValidateBasicRequest(RequestPath, expectedRequestTelemetry); } [Fact] diff --git a/test/Mvc6Framework45.FunctionalTests/project.json b/test/Mvc6Framework45.FunctionalTests/project.json index 8eeab6f..53f3c23 100644 --- a/test/Mvc6Framework45.FunctionalTests/project.json +++ b/test/Mvc6Framework45.FunctionalTests/project.json @@ -28,14 +28,15 @@ "Microsoft.Framework.Logging": "1.0.0-beta4", "Microsoft.Framework.Logging.Console": "1.0.0-beta4", "Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0-beta4", - "xunit.runner.aspnet": "2.0.0-aspnet-beta4-*" + "xunit": "2.1.0-beta2-*", + "xunit.runner.dnx": "2.1.0-beta2-*" }, "commands": { "web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5000", "gen": "Microsoft.Framework.CodeGeneration", "ef": "EntityFramework.Commands", - "test": "xunit.runner.aspnet" + "test": "xunit.runner.dnx" }, "frameworks": { diff --git a/test/WebApiShimFw46.FunctionalTests/FunctionalTest/RequestTelemetryTests.cs b/test/WebApiShimFw46.FunctionalTests/FunctionalTest/RequestTelemetryTests.cs index 5e6cc92..32ee05a 100644 --- a/test/WebApiShimFw46.FunctionalTests/FunctionalTest/RequestTelemetryTests.cs +++ b/test/WebApiShimFw46.FunctionalTests/FunctionalTest/RequestTelemetryTests.cs @@ -13,37 +13,46 @@ [Fact] public void TestBasicRequestPropertiesAfterRequestingValuesController() { + const string RequestPath = "/api/values"; + var expectedRequestTelemetry = new RequestTelemetry(); expectedRequestTelemetry.HttpMethod = "GET"; expectedRequestTelemetry.Name = "GET Values/Get"; expectedRequestTelemetry.ResponseCode = "200"; expectedRequestTelemetry.Success = true; + expectedRequestTelemetry.Url = new System.Uri(this.Server.BaseHost + RequestPath); - this.ValidateBasicRequest("/api/values", expectedRequestTelemetry); + this.ValidateBasicRequest(RequestPath, expectedRequestTelemetry); } [Fact] public void TestBasicRequestPropertiesAfterRequestingNotExistingController() { + const string RequestPath = "/api/notexistingcontroller"; + var expectedRequestTelemetry = new RequestTelemetry(); expectedRequestTelemetry.HttpMethod = "GET"; expectedRequestTelemetry.Name = "GET /api/notexistingcontroller"; expectedRequestTelemetry.ResponseCode = "404"; expectedRequestTelemetry.Success = false; + expectedRequestTelemetry.Url = new System.Uri(this.Server.BaseHost + RequestPath); - this.ValidateBasicRequest("/api/notexistingcontroller", expectedRequestTelemetry); + this.ValidateBasicRequest(RequestPath, expectedRequestTelemetry); } [Fact] public void TestBasicRequestPropertiesAfterRequestingWebApiShimRoute() { + const string RequestPath = "/api/values/1"; + var expectedRequestTelemetry = new RequestTelemetry(); expectedRequestTelemetry.HttpMethod = "GET"; expectedRequestTelemetry.Name = "GET Values/Get [id]"; expectedRequestTelemetry.ResponseCode = "200"; expectedRequestTelemetry.Success = true; + expectedRequestTelemetry.Url = new System.Uri(this.Server.BaseHost + RequestPath); - this.ValidateBasicRequest("/api/values/1", expectedRequestTelemetry); + this.ValidateBasicRequest(RequestPath, expectedRequestTelemetry); } } diff --git a/test/WebApiShimFw46.FunctionalTests/project.json b/test/WebApiShimFw46.FunctionalTests/project.json index 32861dd..03a56c2 100644 --- a/test/WebApiShimFw46.FunctionalTests/project.json +++ b/test/WebApiShimFw46.FunctionalTests/project.json @@ -11,12 +11,13 @@ "Microsoft.AspNet.StaticFiles": "1.0.0-beta4", "Microsoft.AspNet.Mvc.WebApiCompatShim": "6.0.0-beta4", "Microsoft.Framework.ConfigurationModel.Json": "1.0.0-beta4", - "xunit.runner.aspnet": "2.0.0-aspnet-beta4-*" + "xunit": "2.1.0-beta2-*", + "xunit.runner.dnx": "2.1.0-beta2-*" }, "commands": { "web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5000", - "test": "xunit.runner.aspnet" + "test": "xunit.runner.dnx" }, "frameworks": { diff --git a/test/runAllTests.cmd b/test/runAllTests.cmd index aef4cbe..e83a05d 100644 --- a/test/runAllTests.cmd +++ b/test/runAllTests.cmd @@ -1,8 +1,11 @@ -%USERPROFILE%\.dnx\runtimes\dnx-clr-win-x86.1.0.0-beta4\bin\dnx.exe .\Microsoft.ApplicationInsights.AspNet.Tests test -%USERPROFILE%\.dnx\runtimes\dnx-coreclr-win-x86.1.0.0-beta4\bin\dnx.exe .\Microsoft.ApplicationInsights.AspNet.Tests test +@echo off -%USERPROFILE%\.dnx\runtimes\dnx-clr-win-x86.1.0.0-beta4\bin\dnx.exe .\Mvc6Framework45.FunctionalTests test -%USERPROFILE%\.dnx\runtimes\dnx-coreclr-win-x86.1.0.0-beta4\bin\dnx.exe .\Mvc6Framework45.FunctionalTests test +FOR %%A IN (dnx-clr-win-x86.1.0.0-beta4 dnx-coreclr-win-x86.1.0.0-beta4) DO ( + SET DnxPath=%USERPROFILE%\.dnx\runtimes\%%A\bin\dnx.exe -%USERPROFILE%\.dnx\runtimes\dnx-clr-win-x86.1.0.0-beta4\bin\dnx.exe .\WebApiShimFw46.FunctionalTests test -%USERPROFILE%\.dnx\runtimes\dnx-coreclr-win-x86.1.0.0-beta4\bin\dnx.exe .\WebApiShimFw46.FunctionalTests test \ No newline at end of file + ECHO Execting tests on DNX: "%DnxPath% + + %DnxPath% .\Microsoft.ApplicationInsights.AspNet.Tests test -nologo -diagnostics + %DnxPath% .\Mvc6Framework45.FunctionalTests test -nologo -diagnostics + %DnxPath% .\WebApiShimFw46.FunctionalTests test -nologo -diagnostics +) \ No newline at end of file