serilog / serilog-settings-configuration

A Serilog configuration provider that reads from Microsoft.Extensions.Configuration
Apache License 2.0
456 stars 129 forks source link

System.TypeLoadException: Method 'Verbose' in type 'Serilog.Extensions.Hosting.ReloadableLogger' from assembly 'Serilog.Extensions.Hosting' #288

Closed klyse closed 2 years ago

klyse commented 2 years ago

Installed nuget packages

<PackageReference Include="AspNetCore.HealthChecks.NpgSql" Version="5.0.2" />
<PackageReference Include="FluentValidation.AspNetCore" Version="10.3.4" />
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="9.0.0" />
<PackageReference Include="Sentry.AspNetCore" Version="3.10.0" />
<PackageReference Include="Sentry.Serilog" Version="3.9.3" />
<PackageReference Include="Serilog" Version="2.10.0" />
<PackageReference Include="Serilog.AspNetCore" Version="4.1.0" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="4.2.0" />
<PackageReference Include="Serilog.Extensions.Logging" Version="3.1.0" />
<PackageReference Include="Serilog.Formatting.Compact" Version="1.1.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.3.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.0" />
<PackageReference Include="Serilog.Sinks.Debug" Version="2.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="Serilog.Sinks.Fluentd" Version="0.4.0" />
<PackageReference Include="Serilog.Sinks.PeriodicBatching" Version="2.3.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />

Also tried with a more minimalistic set of nugets:

<PackageReference Include="AspNetCore.HealthChecks.NpgSql" Version="5.0.2" />
<PackageReference Include="FluentValidation.AspNetCore" Version="10.3.4" />
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="9.0.0" />
<PackageReference Include="Sentry.AspNetCore" Version="3.10.0" />
<PackageReference Include="Sentry.Serilog" Version="3.10.0" />
<PackageReference Include="Serilog.AspNetCore" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.Fluentd" Version="0.4.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />

OS

Docker

mcr.microsoft.com/dotnet/aspnet:5.0

Additional Information

ASP.Net Core 5.0 app running in a docker container

Code

private static LoggerConfiguration ConfigureLogger(LoggerConfiguration loggerConfig)
{
    loggerConfig
        .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
        .MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning)
        .MinimumLevel.Override("Microsoft.AspNetCore.SignalR", HostingEnvHelper.IsDevelopment ? LogEventLevel.Debug : LogEventLevel.Warning)
        .MinimumLevel.Override("Microsoft.AspNetCore.Http.Connections", HostingEnvHelper.IsDevelopment ? LogEventLevel.Debug : LogEventLevel.Warning)
        .Enrich.FromLogContext()
        .WriteTo.Sentry()
        .WriteTo.Console();

    return loggerConfig;
}

public static int Main(string[] args)
{
    // Serilog.Debugging.SelfLog.Enable(Console.WriteLine);
    Log.Logger = ConfigureLogger(new LoggerConfiguration())
        .MinimumLevel.Debug()
        .CreateBootstrapLogger();
    ....
}
....
public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder
                .UseStartup<Startup>()
                .UseSentry()
                .UseUrls("http://+:5003");
        })
        .UseSerilog((context, _, configuration) =>
            ConfigureLogger(configuration)
                .ReadFrom.Configuration(context.Configuration));

Exception

root@f342f6bbdb2a:/app# dotnet Web.dll
Unhandled exception. System.TypeLoadException: Method 'Verbose' in type 'Serilog.Extensions.Hosting.ReloadableLogger' from assembly 'Serilog.Extensions.Hosting, Version=2.0.0.0, Culture=neutral, PublicKeyToke
n=24c2f752a8e58a10' does not have an implementation.
Aborted

Steps tried to resolve the issue

Hint to where the problem comes from

When changing .CreateBootstrapLogger() to CreateLogger() and adjusting CreateHostBuilder of course the issue is gone.

klyse commented 2 years ago

EDIT: having a detailed .dockerignore makes absolutely sense, but did not solve my issue. The test I made was on a wrong branch.

Found the solution myself. The .dockerignore did not exclude build results and therefore copied the binaries into the container which led to this issue.

Here is the .dockerignore that worked for us:

Web/appsettings.[Dd]evelopment.json
*.env
.envrc
.git
.dockerignore
.gitignore
.vs
.vscode
docker-compose.yml
docker-compose.*.yml
*/bin
*/obj
klyse commented 2 years ago

Having the correct .dockerignore did not solve the issue it just stays the same. I made the test on a wrong branch. Sorry for the confusion.

klyse commented 2 years ago

After some more hours of debugging I found the problem. Finally.

Here is a repo to reproduce the problem: https://github.com/klyse/Serilog-Version-Bug

A lib targeting netstandard2.0 loaded Serilog 2.10.0 while the main project targets net5/6.0 and loadedSerilog.AspNetCore 4.1.0. CreateBootstrapLogger() then tries to resolve a wrong dll and the app does not start.

skomis-mm commented 2 years ago

@klyse , interesting... It looks like the published version of Serilog.dll comes from netstandard2.0 package folder instead of netstandard2.1. Can you check this via reflection tool like ILSpy? image

And web.deps.json should look like

"Serilog/2.10.0": {
  "runtime": {
    "lib/netstandard2.1/Serilog.dll": {
      "assemblyVersion": "2.0.0.0",
      "fileVersion": "2.10.0.0"
    }
  }
}

Is it happens only from docker environment? Looks like a tooling issue, could not reproduce it yet.. (unless manually copy Serilog.dll of netstandard2.0 to the output folder)

skomis-mm commented 2 years ago

Ok, just change the line

dotnet publish -c Release -o out

to

 dotnet publish web -c Release -o out

I read somewhere that publish on .sln is not a recommended way because can have unpredicted results. (Lib published artifacts overwrites Web artifacts). At least, in current tooling (check dotnet/sdk) . Instead, do your publish just for the end project (Web.csproj)

klyse commented 2 years ago

That did the trick! This is awesome, thanks @skomis-mm! I guess the ILSpy is not required anymore.?

skomis-mm commented 2 years ago

@klyse Great! No, ILSpy is not required anymore :)