MiniProfiler / dotnet

A simple but effective mini-profiler for ASP.NET (and Core) websites
https://miniprofiler.com/dotnet/
MIT License
2.92k stars 602 forks source link

Profiling EF Core broken by ConfigureAwait(false) #654

Open RichardD2 opened 1 year ago

RichardD2 commented 1 year ago

Same issue as #392, but this time for EF Core. (v3.1.x in an MVC5 / .NET Framework 4.8 application)

Any use of .ConfigureAwait(false) in the application causes subsequent queries to be missed by the EF Core profiler.

Looking at the RelationalDiagnosticListener class, it makes extensive use of MiniProfiler.Current, which will be null after an awaited call continues without the captured context.

Is there any way to avoid this without dropping every use of .ConfigureAwait(false) from the codebase?

NickCraver commented 1 year ago

@RichardD2 you'll want to use v4+ which has solutions for many of these issues (using AsyncLocal for storage in this case).

RichardD2 commented 1 year ago

@NickCraver I'm using MiniProfiler v4.2.22.

Unfortunately, since we rely on SSRS, we're stuck on .NET Framework, so we can't use any version of EF Core later than v3.1.32.

RichardD2 commented 1 year ago

@NickCraver I see what you mean - the DefaultProfileProvider uses an AsyncLocal, so it should persist across await calls regardless of the ConfigureAwait status.

Perhaps I'm hitting a slightly different problem, but I'm definitely seeing queries missing from the MiniProfiler output when I use ConfigureAwait(false), and included when I remove that.

Maybe it's related to #173?

So far, some of my research as lead me to believe that setting something via AsyncLocal or logical CallContext is not safe from Application_BeginRequest() or any of the ASP.NET pipeline events because the ExecutionContext doesn't flow between the worker threads executing these events. Small/short requests may execute the handler from the same thread that executed Application_BeginRequest(), but larger/long requests may not.

NickCraver commented 1 year ago

@RichardD2 I can't speak to older EF Core issues there - the profiler handles it but EF Core context we have no control over :(