getsentry / sentry-dotnet

Sentry SDK for .NET
https://docs.sentry.io/platforms/dotnet
MIT License
584 stars 206 forks source link

MVC5/Web API integration #168

Closed olsh closed 5 years ago

olsh commented 5 years ago

The old Raven client was able to capture HTTP Context stuff, such as query string, request body, IPrincipal info, etc. It seems like there is no integration with classic MVC/Web API projects.

Are there any plans to implement this?

bruno-garcia commented 5 years ago

We haven't planned this work yet but I agree it makes total sense to add it.

A couple months ago to solve an issue we started multi targeting (.NET Standard and .NET Framework). So now we could, when targeting on .NET Framework (#ifdef NETFX), extract request information for ASP.NET Classic without requiring a new NuGet package like Sentry.AspNet.

Similarly to the AspNetCoreEventProcessor, we could create a AspNetEventProcessor. Something like this:

class AspNetRequestProcessor : ISentryEventProcessor
{
    private readonly SentryOptions _options;

    public AspNetRequestProcessor(SentryOptions options)
    {
        _options = options ?? throw new ArgumentNullException(nameof(options));
    }

    public SentryEvent Process(SentryEvent @event)
    {
        var context = HttpContext.Current;
        if (context == null)
        {
            return @event;
        }

        @event.Request.Method = context.Request.HttpMethod;
        @event.Request.Url = context.Request.Path;

        @event.Request.QueryString = context.Request.QueryString.ToString();
        foreach (var key in context.Request.Headers.AllKeys)
        {
            if (!_options.SendDefaultPii
                // Don't add headers which might contain PII
                && (key == "Cookie"
                    || key == "Authorization"))
            {
                continue;
            }
            @event.Request.Headers[key] = context.Request.Headers[key];
        }

        if (_options?.SendDefaultPii)
        {
            @event.Request.Env["REMOTE_ADDR"] = context.Request.UserHostAddress;
        }

        @event.User.Username = context.User.Identity?.Name;

        @event.Request.Env["SERVER_NAME"] = Environment.MachineName;

        string server = context.Response.Headers["Server"];
        if (server != null)
        {
            @event.Request.Env["SERVER_SOFTWARE"] = server;
        }

        return @event;
    }
}

The main Sentry SDK could add this processor or expose a flag that would add it during Init. It would be great to get some help with this :)

xt0rted commented 5 years ago

This is the setup I used on a site that was mid migration to mvc core. I've been using the ISentryEventProcessor on a number of other non-core sites as well.

https://gist.github.com/xt0rted/c065b5f38d9714bdc953c232cfdf2e09

bruno-garcia commented 5 years ago

@xt0rted quite a few useful things there! Thanks for sharing. One tip is to move the user's Full Name to the newly introduced Other field in the protocol..

xt0rted commented 5 years ago

All that's missing from that gist is the usage of the owin middleware and where the DI method hooks into the existing StructureMap container. If someone wants to use that as a reference it should be pretty straight forward to plug those things in.

Thanks for mentioning the Other field, I'll have to give that a look for my new integrations.

bruno-garcia commented 5 years ago

We've released 1.1.3-beta2 which addresses this. Could you please give it a shot and some feedback?

https://github.com/getsentry/sentry-dotnet/releases/tag/1.1.3-beta2 Feel free to reopen