Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CaptureLastError for ASP.NET #1411

Merged
merged 9 commits into from
Jan 3, 2022
Merged
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Unreleased

## Features

- Add CaptureLastError as an extension method to the Server class on ASP.NET ([#1411](https://github.com/getsentry/sentry-dotnet/pull/1411))
- Add IsDynamicCode* to events ([#1418](https://github.com/getsentry/sentry-dotnet/pull/1418))

## 3.12.3
Expand Down
30 changes: 30 additions & 0 deletions src/Sentry.AspNet/SentryHttpServerUtilityExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System.Web;
using Sentry.Extensibility;
using Sentry.Protocol;

namespace Sentry.AspNet;

/// <summary>
/// HttpServerUtility extensions.
/// </summary>
public static class SentryHttpServerUtilityExtensions
{
/// <summary>
/// Captures the last error from the given HttpServerUtility and sends it to Sentry.
/// </summary>
/// <param name="server">The HttpServerUtility that contains the last error.</param>
/// <returns>A SentryId.</returns>
public static SentryId CaptureLastError(this HttpServerUtility server) => server.CaptureLastError(HubAdapter.Instance);

// for testing
internal static SentryId CaptureLastError(this HttpServerUtility server, IHub hub)
{
if (server.GetLastError() is { } exception)
{
exception.Data[Mechanism.HandledKey] = false;
exception.Data[Mechanism.MechanismKey] = "HttpApplication.Application_Error";
return hub.CaptureException(exception);
}
return SentryId.Empty;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,8 @@ namespace Sentry.AspNet
{
public static void AddAspNet(this Sentry.SentryOptions options, Sentry.Extensibility.RequestSize maxRequestBodySize = 0) { }
}
public static class SentryHttpServerUtilityExtensions
{
public static Sentry.SentryId CaptureLastError(this System.Web.HttpServerUtility server) { }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using System.Web;

namespace Sentry.AspNet.Tests;

public class SentryHttpServerUtilityExtensionsTests
lucas-zimerman marked this conversation as resolved.
Show resolved Hide resolved
{
private class Fixture
{
public SentryId Id { get; set; }

public IHub GetSut()
{
Id = SentryId.Create();
var hub = Substitute.For<IHub>();
hub.IsEnabled.Returns(true);
hub.CaptureEvent(Arg.Any<SentryEvent>()).Returns(Id);
return hub;
}
}

private readonly Fixture _fixture = new();

[Fact]
public void CaptureLastError_WithError_UnhandledErrorCaptured()
{
// Arrange
var hub = _fixture.GetSut();
var exception = new Exception();

var context = new HttpContext(new HttpRequest("", "http://test", null), new HttpResponse(new StringWriter()));
context.AddError(exception);

// Act
var receivedId = context.Server.CaptureLastError(hub);

// Assert
hub.Received(1).CaptureEvent(Arg.Is<SentryEvent>(@event => @event.Exception == exception));
Assert.False(exception.Data[Mechanism.HandledKey] as bool?);
Assert.Equal("HttpApplication.Application_Error", exception.Data[Mechanism.MechanismKey]);
Assert.Equal(_fixture.Id, receivedId);
}

[Fact]
public void CaptureLastError_WithoutError_DoNothing()
{
// Arrange
var hub = _fixture.GetSut();
var context = new HttpContext(new HttpRequest("", "http://test", null), new HttpResponse(new StringWriter()));

// Act
var receivedId = context.Server.CaptureLastError(hub);

// Assert
hub.Received(0).CaptureEvent(Arg.Any<SentryEvent>());
Assert.Equal(SentryId.Empty, receivedId);
}
}