dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.29k stars 9.96k forks source link

Health Check issue with Microsoft.Extensions.Diagnostics.HealthChecks 7.0.0 running on net6.0 #45278

Open Hoaas opened 1 year ago

Hoaas commented 1 year ago

Is there an existing issue for this?

Describe the bug

Having found two "fixes" already this is more a should-it-be-like-this?

Health checks are not working if the package Microsoft.Extensions.Diagnostics.HealthChecks version 7.0.0 is added and you are running .NET 6.

The health endpoints return 500 Internal Server Error and never enter construcor or CheckHealthAsync() method of a custom health check.

Does not occur if:

Expected Behavior

Not for health endpoints to return 500 Internal Server Error.

Steps To Reproduce

Small example here: https://github.com/Hoaas/HealthCheckIssue

Created with dotnet new webapi. Added packages <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions" Version="7.0.0" />

And changed to <TargetFramework>net6.0</TargetFramework>. Added sample health check class from from https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/health-checks?view=aspnetcore-7.0#create-health-checks

Starting and attempting to call /healthz returns 500.

Exceptions (if any)

System.AggregateException: An error occurred while writing to logger(s). (Could not load file or assembly 'Microsoft.Bcl.AsyncInterfaces, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. The system cannot find the file specified.) (Could not load file or assembly 'Microsoft.Bcl.AsyncInterfaces, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. The system cannot find the file specified.)
       ---> System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.Bcl.AsyncInterfaces, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. The system cannot find the file specified.
      File name: 'Microsoft.Bcl.AsyncInterfaces, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'
         at System.Reflection.CustomAttribute._CreateCaObject(RuntimeModule pModule, RuntimeType type, IRuntimeMethodInfo pCtor, Byte** ppBlob, Byte* pEndBlob, Int32* pcNamedArgs)
         at System.Reflection.CustomAttribute.AddCustomAttributes(ListBuilder`1& attributes, RuntimeModule decoratedModule, Int32 decoratedMetadataToken, RuntimeType attributeFilterType, Boolean mustBeInheritable, ListBuilder`1 derivedAttributes)
         at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeModule decoratedModule, Int32 decoratedMetadataToken, Int32 pcaCount, RuntimeType attributeFilterType)
         at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeMethodInfo method, RuntimeType caType, Boolean inherit)
         at System.Reflection.RuntimeMethodInfo.GetCustomAttributes(Type attributeType, Boolean inherit)
         at System.Attribute.GetCustomAttributes(MemberInfo element, Type attributeType, Boolean inherit)
         at System.Reflection.CustomAttributeExtensions.GetCustomAttributes[T](MemberInfo element, Boolean inherit)
         at System.Diagnostics.StackTrace.TryResolveStateMachineMethod(MethodBase& method, Type& declaringType)
         at System.Diagnostics.StackTrace.ToString(TraceFormat traceFormat, StringBuilder sb)
         at System.Diagnostics.StackTrace.ToString(TraceFormat traceFormat)
         at System.Exception.get_StackTrace()
         at System.IO.FileNotFoundException.ToString()
         at Microsoft.Extensions.Logging.Console.SimpleConsoleFormatter.CreateDefaultLogMessage[TState](TextWriter textWriter, LogEntry`1& logEntry, String message, IExternalScopeProvider scopeProvider)
         at Microsoft.Extensions.Logging.Console.SimpleConsoleFormatter.Write[TState](LogEntry`1& logEntry, IExternalScopeProvider scopeProvider, TextWriter textWriter)
         at Microsoft.Extensions.Logging.Console.ConsoleLogger.Log[TState](LogLevel logLevel, EventId eventId, TState state, Exception exception, Func`3 formatter)
         at Microsoft.Extensions.Logging.Logger.<Log>g__LoggerLog|12_0[TState](LogLevel logLevel, EventId eventId, ILogger logger, Exception exception, Func`3 formatter, List`1& exceptions, TState& state)
         --- End of inner exception stack trace ---
         at Microsoft.Extensions.Logging.Logger.ThrowLoggingError(List`1 exceptions)
         at Microsoft.Extensions.Logging.Logger.Log[TState](LogLevel logLevel, EventId eventId, TState state, Exception exception, Func`3 formatter)
         at Microsoft.Extensions.Logging.Logger`1.Microsoft.Extensions.Logging.ILogger.Log[TState](LogLevel logLevel, EventId eventId, TState state, Exception exception, Func`3 formatter)
         at Microsoft.Extensions.Logging.LoggerMessage.<>c__DisplayClass8_0.<Define>g__Log|0(ILogger logger, Exception exception)
         at Microsoft.AspNetCore.Diagnostics.DiagnosticsLoggerExtensions.UnhandledException(ILogger logger, Exception exception)
         at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
         at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
       ---> (Inner Exception #1) System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.Bcl.AsyncInterfaces, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. The system cannot find the file specified.
      File name: 'Microsoft.Bcl.AsyncInterfaces, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'
         at System.Reflection.CustomAttribute._CreateCaObject(RuntimeModule pModule, RuntimeType type, IRuntimeMethodInfo pCtor, Byte** ppBlob, Byte* pEndBlob, Int32* pcNamedArgs)
         at System.Reflection.CustomAttribute.AddCustomAttributes(ListBuilder`1& attributes, RuntimeModule decoratedModule, Int32 decoratedMetadataToken, RuntimeType attributeFilterType, Boolean mustBeInheritable, ListBuilder`1 derivedAttributes)
         at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeModule decoratedModule, Int32 decoratedMetadataToken, Int32 pcaCount, RuntimeType attributeFilterType)
         at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeMethodInfo method, RuntimeType caType, Boolean inherit)
         at System.Reflection.RuntimeMethodInfo.GetCustomAttributes(Type attributeType, Boolean inherit)
         at System.Attribute.GetCustomAttributes(MemberInfo element, Type attributeType, Boolean inherit)
         at System.Reflection.CustomAttributeExtensions.GetCustomAttributes[T](MemberInfo element, Boolean inherit)
         at System.Diagnostics.StackTrace.TryResolveStateMachineMethod(MethodBase& method, Type& declaringType)
         at System.Diagnostics.StackTrace.ToString(TraceFormat traceFormat, StringBuilder sb)
         at System.Diagnostics.StackTrace.ToString(TraceFormat traceFormat)
         at System.Exception.get_StackTrace()
         at System.IO.FileNotFoundException.ToString()
         at System.Text.StringBuilder.Append(Object value)
         at Microsoft.Extensions.Logging.EventLog.EventLogLogger.Log[TState](LogLevel logLevel, EventId eventId, TState state, Exception exception, Func`3 formatter)
         at Microsoft.Extensions.Logging.Logger.<Log>g__LoggerLog|12_0[TState](LogLevel logLevel, EventId eventId, ILogger logger, Exception exception, Func`3 formatter, List`1& exceptions, TState& state)<---

.NET Version

7.0.11

Anything else?

No response

martincostello commented 1 year ago

Using 7.0.x packages isn't supported with .NET 6: https://github.com/dotnet/aspnetcore/issues/45149#issuecomment-1320517662

Tratcher commented 1 year ago

Team: Remind me why this package cross targets .NET 7, Netstandard 2.0, and .NET 4.6.x? If it only targeted .NET 7 then you wouldn't even be able to install it on .NET 6.

adityamandaleeka commented 1 year ago

Triage: Consider dropping .NET 4.6.x and netstandard from this package in the 8.0 version.

ghost commented 1 year ago

Thanks for contacting us.

We're moving this issue to the .NET 8 Planning milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s). If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues. To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

kevinchalet commented 1 year ago

Triage: Consider dropping .NET 4.6.x and netstandard from this package in the 8.0 version.

Please don't do that: this package is very useful on .NET Framework to bring some health checks love to good old Katana applications (see https://github.com/ritterim/RimDev.AspNet.Diagnostics.HealthChecks for a community project that uses the health checks stack).

Using 7.0.x packages isn't supported with .NET 6: #45149 (comment)

It's worth noting this rule is no longer strictly enforced by some of the .NET teams: EF Core 7.0 targets net6.0 and references Microsoft.Extensions.* 7.0.0 packages, which causes weird issues in .NET 6.0 applications like the ones reported here.

Tratcher commented 1 year ago

@kevinchalet is there a reason that the .NET 8 version of this package is needed on .NET 4.x? Can't any of the prior versions be used?

kevinchalet commented 1 year ago

Sure: the health checks stack was only introduced in ASP.NET Core 2.2 so there's no "super-long-term" 2.1 version available. If you stop shipping this package, .NET Framework users will be left in an unsupported state when .NET 6.0/7.0 reach end of life.

Tratcher commented 1 year ago

Sounds like we should just move the package to the 2.1 branch then 😁.

kevinchalet commented 1 year ago

That would be one (great) way to solve that, but AFAIK, "no new API in patches" has always been the rule here. Shipping whole new packages in a 2.1 patch would be a hard sell 🀣

Tratcher commented 1 year ago

I've done it before with WsFed :-). New packages are actually easier than APIs.

kevinchalet commented 1 year ago

Ah! In this case... πŸ‘πŸ» (it's Christmas in less than a month... 🀣)

Willow766 commented 1 year ago

.Net 6 assembly utilizing Package v 6.0.13 This issue just "appeared" one day. At what point does Microsoft go back to being a professionally organized company (instead of a gaggle of independent developers?)?? You're starting to get badmouthed pretty regularly among those of us who didn't hang our hats on your tech. I believe you have one of the best RAD platforms, but you're ruining it with a lack of coordination. There is absolutely NO reason for this error in .Net 6 except irresponsible coding. - NO EXCUSE!

ShvetsovZE commented 12 months ago

I have exactly the same issue with .net7, and AddAzureBlobStorage health check.

jtullos-bt commented 10 months ago

@Hoaas If you add the Microsoft.Bcl.AsyncInterfaces nuget to your project it does work. I ran into this yesterday. I'm probably going to downgrade until we upgrade the entire solution to .NET7+ :(

chrisbuttacavoliadec commented 10 months ago

Why is this even allowed to be downloaded to .NET 6 platforms? I just ran into this issue myself installing AspNetCore.HealthChecks.SqlServer v7.0.0, which I suspect has the same root cause. Rolling back to the v6 fixed it. Thank you for opening this issue so I was able to resolve it quicker.4

ajivener commented 9 months ago

I can confirm that the issue is now addressed in that I'm able to use the following package versions in my .NET6 projects without issue after upgrading to the version 8.0.0 packages. HealthcheckWorking

TomasMalecek commented 2 months ago

Ad https://github.com/dotnet/aspnetcore/issues/45278#issuecomment-1327903662: Is this policy documented? I always wondered whether to ignore those package updates offered by NuGet before upgrading the targeting of my projects or whether updating the packages immediately is safe. Being able to mindlessly keep all packages at their latest versions would be great.

As far as I know, the Microsoft.Extensions.* packages usually support even all older but still supported TFMs. Before .NET 6, the DLLs for those older TFMs used to be harvested from the previous major versions of the package, but that kept them from being serviced, so this practice was dropped: https://learn.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/6.0/older-framework-versions-dropped

E.g. Microsoft.Extensions.DependencyInjection.Abstractions (source in the dotnet/runtime repo) version 8.0.1 (current latest GA) still explicitly targets even .NET 6 and .NET 7: https://www.nuget.org/packages/Microsoft.Extensions.DependencyInjection.Abstractions/8.0.1#supportedframeworks-body-tab