missing items after upgrade to Mindscape.Raygun4Net.AspNetCore 11.0.3 from 9.0.4

Dave S

Posted on
Jul 29 2024

We have a series of asp.net core web applications that have been running fine for a long time under 9.0.4 and we are working on upgrading those apps to .net 8 and 11.0.3 of the raygun package.

After updating the package we see two major errors:

In the startup where we have:

           services.AddRaygun(Configuration, new RaygunMiddlewareSettings()
        {
            ClientProvider = new RaygunAspNetCoreClientProvider()
        });

We get an error that RaygunMiddlewareSettings is missing or unable to be located.

In our custom client provider that looks like this (this is just a sample):

public class RaygunAspNetCoreClientProvider : DefaultRaygunAspNetCoreClientProvider

{ public override RaygunClient GetClient(RaygunSettings settings, HttpContext context) { var client = base.GetClient(settings, context);

    client.ApplicationVersion = System.Reflection.Assembly.GetEntryAssembly().GetName().Version.ToString();

    client.SendingMessage += (sender, args) =>
    {
        // This is an example of cancelling a message:
        if (args.Message.Details.Error.ClassName == "System.OperationCanceledException" || args.Message.Details.Error.ClassName == "System.Threading.Tasks.TaskCanceledException" || args.Message.Details.Error.ClassName == "Microsoft.AspNetCore.Connections.ConnectionResetException")
        {
            args.Cancel = true;
        }

    };

    return client;
}

}

we get that DefaultRaygunAspNetCoreClientProvider is missing and cannot be found.

I have double checked package references and using statements and all look good. However it will no longer compile with the new package. If I downgrade to 9.0.4 it compiles just fine. Something appears broken.

I tried submitting a prob request via the web form but haven't heard back so submitting here - sorry if that causes more work on your end. We just need a resolution.

Thanks, Dave


Jasen

Raygun

Posted on
Jul 30 2024

Hi Dave,

There have been some breaking changes between version 9 and 11 of the raygun4net provider. The full change log can be found here.

Specifically for you, RaygunMiddlewareSettings and DefaultRaygunAspNetCoreClientProvider have been removed in favour of a singleton approach to the RaygunClient.

Translating your setup to the new approach would look something like this:

services.AddSingleton(s => 
{
  var client = new RaygunClient(s.GetService<RaygunSettings>()!, s.GetService<IRaygunUserProvider>()!);

  client.SendingMessage += (sender, args) =>
  {
        if (args.Message.Details.Error.ClassName == "System.OperationCanceledException" ||
            args.Message.Details.Error.ClassName == "System.Threading.Tasks.TaskCanceledException" ||
            args.Message.Details.Error.ClassName == "Microsoft.AspNetCore.Connections.ConnectionResetException")
        {
            args.Cancel = true;
        }
  };

  return client;
});

services.AddRaygun(Configuration, settings => 
{
  settings.ApplicationVersion = System.Reflection.Assembly.GetEntryAssembly().GetName().Version.ToString();
});

See this GitHub issue for more information about the SendingMessage event.

Let me know if there is anything else you need assistance with.

Kind regards,

Jasen


Dave S

Posted on
Jul 30 2024

These changes are going to result in lots of effort on our part.

I have looked at the singleton documentation (https://raygun.com/documentation/language-guides/dotnet/crash-reporting/aspnet/)

You say here that we should manually set the httpContext prior to manually sending messages, but in the singleton client that is passed to the controller I am not finding the method for doing this that you reference?

In specific, there is no SetCurrentContext(HttpContext) method.

However I am seeing an overload on SendInBackground that will accept the HttpContext. Is that the proper way for doing it? Your documentation for these changes seems incorrect?

And, I think some real notice should have gone out to users prior to making structural changes like this between builds. If it did I didn't receive it.


PHaydon

Raygun

Posted on
Jul 31 2024

Hello Dave,

Based on the original post I don't think you need to make lots of changes.

As Jasen showed, it should be a case of moving the code in the RaygunAspNetCoreClientProvider class to your registration.

So:

services.AddRaygun(Configuration, new RaygunMiddlewareSettings()
{
    ClientProvider = new RaygunAspNetCoreClientProvider()
});

To:

services.AddSingleton(s => 
{
    var client = new RaygunClient(s.GetService<RaygunSettings>()!, s.GetService<IRaygunUserProvider>()!);

    client.SendingMessage += (sender, args) =>
    {
        if (args.Message.Details.Error.ClassName == "System.OperationCanceledException" ||
            args.Message.Details.Error.ClassName == "System.Threading.Tasks.TaskCanceledException" ||
            args.Message.Details.Error.ClassName == "Microsoft.AspNetCore.Connections.ConnectionResetException")
        {
            args.Cancel = true;
        }
    };

    return client;
});

services.AddRaygun(Configuration, settings => 
{
    settings.ApplicationVersion = System.Reflection.Assembly.GetEntryAssembly().GetName().Version.ToString();
});

If you want to handle errors yourself in your controller you can inject the RaygunClient and call SendInBackground:

public class TestController
{
    private RaygunClient _client;

    public TestController(RaygunClient client)
    {
        _client = client;
    }

    public async Task<IActionResult> DoSomething()
    {
        try
        {
            throw new Exception("Throwing things");
        }
        catch (Exception e)
        {
            // If you want HTTP Request Data
            await _client.SendInBackground(ex, null, HttpContext);

            // If you don't want HTTP Request Data
            await _client.SendInBackground(ex);
        }
    }
}

We don't like making breaking changes and we try to minimize them as much as possible. The major reasoning for alot of these changes are that we treated the RaygunClient as transient, and this can cause some problems with applications that have a high number of errors being raised. For example, in Azure it can cause thread exhaustion, and in other cases it can generally cause high memory usage and/or thread count.

Typically we would mark apis as Obsolete for a period of time before deciding to remove them, however these particular APIs had to break in order for us to better the RaygunClient. We do indicate this with semantic versioning and have a change log in the repository which is linked from Nuget.

While the new features of collecting Environment variables, added support for breadcrumbs, offline storage, as well as performance improvements. I do think its worth the effort to upgrade.

Thank you. Phill


Dave S

Posted on
Jul 31 2024

So Phil,

I think you are missing my main point. I understand the need of breaking changes from time to time - we deal with them in various components we use.

You misunderstand the scope of our work: we using custom sending and every controller and every controller method is affected by this change across some 20 applications. Non trivial. Can it be dealt with? Sure but it involves a lot of unexpected work during a normal update cycle.

You should be providing prior notice of breaking changes like most other vendors do. It allows us, as a customer, to factor in the work required to our normal change mgt process instead of walking into a buzzsaw of unexpected work.

Your documentation (atleast on the .net side) seems to be incomplete related to this change. You mention using a singleton approach but none was provided as a sample. Your area on custom sending was just wrong apparently in dealing with httpContext.

I agree a singleton approach makes more sense over transients. But - what would have been helpful is good sample documentation on the change and prior notice to see where method changes exist, etc. A quick good sample solves lots of issues instead of me having to take days of back and forth in a forum or in email due to timezone differences.

Thanks for your help on this - and please do take these requests to heart.


PHaydon

Raygun

Posted on
Jul 31 2024

Hey Dave,

Thank you for the feedback, we do appreciate it and I've passed it on.

I think if you're not suffering from any thread exhaustion or similar issues, you could defer upgrading the library for the time being.

If you do want to go ahead with the upgrade and the time consuming bit is the custom handling, it may speed things up to use regex find/replace:

enter image description here

find:

([a-zA-Z]+).SetCurrentContext(HttpContext);[\n\r]\W+(?:await\W)?[a-zA-Z]+.SendAsync(([a-zA-Z]+));

replace:

await $1.SendInBackground($2, null, HttpContext)

I found this way helpful when fixing 1000s of unit tests in NUnit when their API changed.

I do apologize for the inconvenience that this API change causes you, we really do try hard to not break APIs or at least obsolete them first, this one was unavoidable and I believe probably the biggest API change we've had to make.

Thank you.

Phill


Reply