Skip to content
This repository was archived by the owner on Jul 5, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@


## Version 2.6.0-beta2
- [Implement unhandled exception auto-tracking (500 requests) for MVC 5 and WebAPI 2 applications] (https://github.com/Microsoft/ApplicationInsights-dotnet-server/pull/847)
- [Added a max length restriction to values passed in through requests.](https://github.com/Microsoft/ApplicationInsights-dotnet-server/pull/810)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add your comment to "2.6.0-beta3". Beta 2 is being released this week. I can explain offline.

- [Fix: Dependency Telemetry is not collected with DiagnosticSource when response does not have content.](https://github.com/Microsoft/ApplicationInsights-dotnet-server/issues/739)
- [Expose Request-Context in Access-Control-Expose-Headers header, and that allows cross-component correlation between AJAX dependencies and server-side requests.](https://github.com/Microsoft/ApplicationInsights-dotnet-server/issues/802)
Expand Down
155 changes: 155 additions & 0 deletions Src/Web/Web.Net45.Tests/MvcExceptionHandlerTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
namespace Microsoft.ApplicationInsights.Web
{
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Web.Mvc;
using Microsoft.ApplicationInsights.Channel;
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.ApplicationInsights.Web.Helpers;
using Microsoft.ApplicationInsights.Web.TestFramework;
using Microsoft.VisualStudio.TestTools.UnitTesting;

[TestClass]
public class MvcExceptionHandlerTests
{
private ConcurrentQueue<ExceptionTelemetry> sentTelemetry;
private TelemetryConfiguration configuration;

[TestInitialize]
public void TestInit()
{
GlobalFilters.Filters.Clear();
this.sentTelemetry = new ConcurrentQueue<ExceptionTelemetry>();

var stubTelemetryChannel = new StubTelemetryChannel
{
OnSend = t =>
{
if (t is ExceptionTelemetry telemetry)
{
this.sentTelemetry.Enqueue(telemetry);
}
}
};

this.configuration = new TelemetryConfiguration
{
InstrumentationKey = Guid.NewGuid().ToString(),
TelemetryChannel = stubTelemetryChannel
};
}

[TestCleanup]
public void Cleanup()
{
while (this.sentTelemetry.TryDequeue(out var _))
{
}

GlobalFilters.Filters.Clear();
}

[TestMethod]
public void MvcExceptionFilterIsInjectedAndTracksException()
{
using (var exceptionModule = new ExceptionTrackingTelemetryModule())
{
exceptionModule.Initialize(this.configuration);

var mvcExceptionFilters = GlobalFilters.Filters;
Assert.AreEqual(1, mvcExceptionFilters.Count);

var handleExceptionFilter = (HandleErrorAttribute)mvcExceptionFilters.Single().Instance;
Assert.IsNotNull(handleExceptionFilter);

var exception = new Exception("test");
var controllerCtx = HttpModuleHelper.GetFakeControllerContext(isCustomErrorEnabled: true);
handleExceptionFilter.OnException(new ExceptionContext(controllerCtx, exception));

Assert.AreEqual(1, this.sentTelemetry.Count);

var trackedException = this.sentTelemetry.Single();
Assert.IsNotNull(trackedException);
Assert.AreEqual(exception, trackedException.Exception);
}
}

[TestMethod]
public void MvcExceptionFilterIsNotInjectedIsInjectionIsDisabled()
{
using (var exceptionModule = new ExceptionTrackingTelemetryModule())
{
exceptionModule.EnableMvcAndWebApiExceptionAutoTracking = false;
exceptionModule.Initialize(this.configuration);

Assert.IsFalse(GlobalFilters.Filters.Any());
}
}

[TestMethod]
public void MvcExceptionLoggerIsNotInjectedIfAnotherInjectionDetected()
{
GlobalFilters.Filters.Add(new MvcAutoInjectedFilter());
Assert.AreEqual(1, GlobalFilters.Filters.Count);

using (var exceptionModule = new ExceptionTrackingTelemetryModule())
{
exceptionModule.Initialize(this.configuration);

var filters = GlobalFilters.Filters;
Assert.AreEqual(1, filters.Count);
Assert.IsInstanceOfType(filters.Single().Instance, typeof(MvcAutoInjectedFilter));
}
}

[TestMethod]
public void MvcExceptionFilterNoopIfCustomErrorsIsFalse()
{
using (var exceptionModule = new ExceptionTrackingTelemetryModule())
{
exceptionModule.Initialize(this.configuration);

var mvcExceptionFilters = GlobalFilters.Filters;
Assert.AreEqual(1, mvcExceptionFilters.Count);

var handleExceptionFilter = (HandleErrorAttribute)mvcExceptionFilters.Single().Instance;
Assert.IsNotNull(handleExceptionFilter);

var exception = new Exception("test");
var controllerCtx = HttpModuleHelper.GetFakeControllerContext(isCustomErrorEnabled: false);
handleExceptionFilter.OnException(new ExceptionContext(controllerCtx, exception));

Assert.IsFalse(this.sentTelemetry.Any());
}
}

[TestMethod]
public void MvcExceptionFilterNoopIfExceptionIsNull()
{
using (var exceptionModule = new ExceptionTrackingTelemetryModule())
{
exceptionModule.Initialize(this.configuration);

var mvcExceptionFilters = GlobalFilters.Filters;
Assert.AreEqual(1, mvcExceptionFilters.Count);

var handleExceptionFilter = (HandleErrorAttribute)mvcExceptionFilters.Single().Instance;
Assert.IsNotNull(handleExceptionFilter);

var controllerCtx = HttpModuleHelper.GetFakeControllerContext(isCustomErrorEnabled: true);
var exceptionContext = new ExceptionContext(controllerCtx, new Exception());
exceptionContext.Exception = null;
handleExceptionFilter.OnException(exceptionContext);

Assert.IsFalse(this.sentTelemetry.Any());
}
}

private class MvcAutoInjectedFilter : HandleErrorAttribute
{
public const bool IsAutoInjected = true;
}
}
}
54 changes: 52 additions & 2 deletions Src/Web/Web.Net45.Tests/Web.Net45.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), 'Test.props'))\Test.props" />
<PropertyGroup>
Expand All @@ -25,25 +25,73 @@
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' " />
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' " />
<ItemGroup>
<Reference Include="Castle.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\Castle.Core.4.2.1\lib\net45\Castle.Core.dll</HintPath>
</Reference>
<Reference Include="Microsoft.ApplicationInsights, Version=2.6.0-beta2, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\Microsoft.ApplicationInsights.2.6.0-beta2\lib\net45\Microsoft.ApplicationInsights.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.WindowsAzure.ServiceRuntime, Version=2.4.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\Web.Shared.Net.Tests\Azure\Emulation\Microsoft.WindowsAzure.ServiceRuntime.dll</HintPath>
</Reference>
<Reference Include="Moq, Version=4.8.0.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\Moq.4.8.2\lib\net45\Moq.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework" />
<Reference Include="System.Configuration" />
<Reference Include="System.Diagnostics.DiagnosticSource, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\System.Diagnostics.DiagnosticSource.4.4.0\lib\net45\System.Diagnostics.DiagnosticSource.dll</HintPath>
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.Management" />
<Reference Include="System.Net" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Net.Http.Formatting, Version=5.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\Microsoft.AspNet.WebApi.Client.5.2.4\lib\net45\System.Net.Http.Formatting.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.Remoting" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Threading.Tasks.Extensions, Version=4.1.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\System.Threading.Tasks.Extensions.4.3.0\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.ValueTuple, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\System.ValueTuple.4.4.0\lib\netstandard1.0\System.ValueTuple.dll</HintPath>
</Reference>
<Reference Include="System.Web" />
<Reference Include="System.Web.Helpers, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\Microsoft.AspNet.WebPages.3.2.4\lib\net45\System.Web.Helpers.dll</HintPath>
</Reference>
<Reference Include="System.Web.Http, Version=5.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\Microsoft.AspNet.WebApi.Core.5.2.4\lib\net45\System.Web.Http.dll</HintPath>
</Reference>
<Reference Include="System.Web.Http.WebHost, Version=5.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\Microsoft.AspNet.WebApi.WebHost.5.2.4\lib\net45\System.Web.Http.WebHost.dll</HintPath>
</Reference>
<Reference Include="System.Web.Mvc, Version=5.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\Microsoft.AspNet.Mvc.5.2.4\lib\net45\System.Web.Mvc.dll</HintPath>
</Reference>
<Reference Include="System.Web.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\Microsoft.AspNet.Razor.3.2.4\lib\net45\System.Web.Razor.dll</HintPath>
</Reference>
<Reference Include="System.Web.WebPages, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\Microsoft.AspNet.WebPages.3.2.4\lib\net45\System.Web.WebPages.dll</HintPath>
</Reference>
<Reference Include="System.Web.WebPages.Deployment, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\Microsoft.AspNet.WebPages.3.2.4\lib\net45\System.Web.WebPages.Deployment.dll</HintPath>
</Reference>
<Reference Include="System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\..\packages\Microsoft.AspNet.WebPages.3.2.4\lib\net45\System.Web.WebPages.Razor.dll</HintPath>
</Reference>
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
Expand Down Expand Up @@ -76,7 +124,9 @@
</ItemGroup>
<ItemGroup>
<Compile Include="AspNetDiagnosticTelemetryModuleTest.cs" />
<Compile Include="MvcExceptionHandlerTests.cs" />
<Compile Include="RequestTrackingTelemetryModuleTest.Net45.cs" />
<Compile Include="WebApiExceptionLoggerTests.cs" />
</ItemGroup>
<Import Project="..\Web.Shared.Net.Tests\Web.Shared.Net.Tests.projitems" Label="Shared" />
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
Expand All @@ -90,4 +140,4 @@
</PropertyGroup>
<Error Condition="!Exists('..\..\..\..\packages\StyleCop.MSBuild.5.0.0\build\StyleCop.MSBuild.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\StyleCop.MSBuild.5.0.0\build\StyleCop.MSBuild.targets'))" />
</Target>
</Project>
</Project>
103 changes: 103 additions & 0 deletions Src/Web/Web.Net45.Tests/WebApiExceptionLoggerTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
namespace Microsoft.ApplicationInsights
{
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Web.Http;
using System.Web.Http.ExceptionHandling;
using Microsoft.ApplicationInsights.Channel;
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.ApplicationInsights.Web;
using Microsoft.ApplicationInsights.Web.TestFramework;
using Microsoft.VisualStudio.TestTools.UnitTesting;

[TestClass]
public class WebApiExceptionLoggerTests
{
private ConcurrentQueue<ITelemetry> sentTelemetry;
private TelemetryConfiguration configuration;

[TestInitialize]
public void TestInit()
{
GlobalConfiguration.Configuration.Services.Clear(typeof(IExceptionLogger));
this.sentTelemetry = new ConcurrentQueue<ITelemetry>();

var stubTelemetryChannel = new StubTelemetryChannel
{
OnSend = t =>
{
if (t is ExceptionTelemetry telemetry)
{
this.sentTelemetry.Enqueue(telemetry);
}
}
};

this.configuration = new TelemetryConfiguration
{
InstrumentationKey = Guid.NewGuid().ToString(),
TelemetryChannel = stubTelemetryChannel
};
}

[TestCleanup]
public void Cleanup()
{
while (this.sentTelemetry.TryDequeue(out var _))
{
}

GlobalConfiguration.Configuration.Services.Clear(typeof(IExceptionLogger));
}

[TestMethod]
public void WebApiExceptionLoggerIsInjectedAndTracksException()
{
Assert.IsFalse(GlobalConfiguration.Configuration.Services.GetServices(typeof(IExceptionLogger)).Any());

using (var exceptionModule = new ExceptionTrackingTelemetryModule())
{
exceptionModule.Initialize(this.configuration);

var webApiExceptionLoggers = GlobalConfiguration.Configuration.Services.GetServices(typeof(IExceptionLogger)).ToList();
Assert.AreEqual(1, webApiExceptionLoggers.Count);

var logger = (ExceptionLogger)webApiExceptionLoggers[0];
Assert.IsNotNull(logger);

var exception = new Exception("test");
var exceptionContext = new ExceptionLoggerContext(new ExceptionContext(exception, new ExceptionContextCatchBlock("catch block name", true, false)));
logger.Log(exceptionContext);

Assert.AreEqual(1, this.sentTelemetry.Count);

var trackedException = (ExceptionTelemetry)this.sentTelemetry.Single();
Assert.IsNotNull(trackedException);
Assert.AreEqual(exception, trackedException.Exception);
}
}

[TestMethod]
public void WebApiExceptionLoggerIsNotInjectedIfAnotherInjectionDetected()
{
GlobalConfiguration.Configuration.Services.Add(typeof(IExceptionLogger), new WebApiAutoInjectedLogger());
Assert.AreEqual(1, GlobalConfiguration.Configuration.Services.GetServices(typeof(IExceptionLogger)).Count());

using (var exceptionModule = new ExceptionTrackingTelemetryModule())
{
exceptionModule.Initialize(this.configuration);

var loggers = GlobalConfiguration.Configuration.Services.GetServices(typeof(IExceptionLogger)).ToList();
Assert.AreEqual(1, loggers.Count);
Assert.IsInstanceOfType(loggers.Single(), typeof(WebApiAutoInjectedLogger));
}
}

private class WebApiAutoInjectedLogger : ExceptionLogger
{
public const bool IsAutoInjected = true;
}
}
}
17 changes: 15 additions & 2 deletions Src/Web/Web.Net45.Tests/packages.config
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Castle.Core" version="4.2.1" targetFramework="net451" />
<package id="Microsoft.ApplicationInsights" version="2.6.0-beta2" targetFramework="net451" />
<package id="Microsoft.AspNet.Mvc" version="5.2.4" targetFramework="net451" />
<package id="Microsoft.AspNet.Razor" version="3.2.4" targetFramework="net451" />
<package id="Microsoft.AspNet.WebApi" version="5.2.4" targetFramework="net451" />
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.4" targetFramework="net451" />
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.4" targetFramework="net451" />
<package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.4" targetFramework="net451" />
<package id="Microsoft.AspNet.WebPages" version="3.2.4" targetFramework="net451" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net451" />
<package id="Moq" version="4.8.2" targetFramework="net451" />
<package id="Newtonsoft.Json" version="6.0.4" targetFramework="net451" />
<package id="OpenCover" version="4.6.519" targetFramework="net451" />
<package id="StyleCop.MSBuild" version="5.0.0" targetFramework="net451" developmentDependency="true" />
<package id="System.Diagnostics.DiagnosticSource" version="4.4.0" targetFramework="net451" />
<package id="System.Threading.Tasks.Extensions" version="4.3.0" targetFramework="net451" />
<package id="System.ValueTuple" version="4.4.0" targetFramework="net451" />
<package id="xunit" version="2.1.0" targetFramework="net451" />
<package id="xunit.abstractions" version="2.0.0" targetFramework="net451" />
<package id="xunit.assert" version="2.1.0" targetFramework="net451" />
<package id="xunit.core" version="2.1.0" targetFramework="net451" />
<package id="xunit.extensibility.core" version="2.1.0" targetFramework="net451" />
<package id="xunit.extensibility.execution" version="2.1.0" targetFramework="net451" />
</packages>
</packages>
Loading