dotnet / extensions

This repository contains a suite of libraries that provide facilities commonly needed when creating production-ready applications.
MIT License
2.59k stars 743 forks source link

`Microsoft.Extensions.Telemetry.Abstractions` doesn't find protected field `ILogger` for `[LoggerMessage]` #5221

Closed ValeriyGourov closed 4 weeks ago

ValeriyGourov commented 3 months ago

Description

We have an ASP.NET Core 8 application. There are two classes: Base and Derived. Derived inherits from Base. Base contains a protected field ILogger which is used for logging in both classes.

When we added logging methods with LoggerMessageAttribute, they work as expected in both classes using the ILogger field from base class. But if we add the Microsoft.Extensions.Telemetry.Abstractions package, then we immediately have an error in the derived class:

LOGGEN015 Couldn't find a field or property of type "Microsoft.Extensions.Logging.ILogger" in type "Derived"

There is no such error in the base class.

Reproduction Steps

Here's the .csproj definition:

<Project Sdk="Microsoft.NET.Sdk.Web">

    <PropertyGroup>
        <TargetFramework>net8.0</TargetFramework>
        <Nullable>enable</Nullable>
        <ImplicitUsings>enable</ImplicitUsings>
    </PropertyGroup>

    <ItemGroup>
<!--        <PackageReference Include="Microsoft.Extensions.Telemetry.Abstractions" Version="8.6.0" />-->
    </ItemGroup>

</Project>

Program.cs:

WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
WebApplication app = builder.Build();

app.MapGet("/", () => "Hello World!");

await app.RunAsync();

public abstract partial class Base(ILogger<Base> logger)
{
    protected readonly ILogger<Base> _logger = logger;

    public void BaseMethod()
    {
        LogInformationBase();
    }

    [LoggerMessage(Level = LogLevel.Information, Message = "Base LoggerMessage")]
    private partial void LogInformationBase();
}

public partial class Derived(ILogger<Derived> logger)
    : Base(logger)
{
    public void DerivedMethod()
    {
        _logger.LogInformation("Derived");
        LogInformationDerived();
    }

    [LoggerMessage(Level = LogLevel.Information, Message = "Derived LoggerMessage")]
    private partial void LogInformationDerived();
}

There is no error in this configuration.

To get the error, we should uncomment the PackageReference item in the .csproj file. After this, we will have an error:

image

Expected behavior

In this situation, the source code generator from the Microsoft.Extensions.Telemetry.Abstractions package should behave like the source code generator from the Microsoft.Extensions.Logging.Abstractions package. When we use [LoggerMessage] in a derived class, it must find a protected field ILogger from the base class.

Actual behavior

When we use the Microsoft.Extensions.Telemetry.Abstractions package, the source code generator doesn't find a protected field ILogger from the base class.

Regression?

Regression compared to the Microsoft.Extensions.Logging.Abstractions package.

Known Workarounds

No response

Configuration

dotnet --info

ПАКЕТ SDK ДЛЯ .NET: Version: 8.0.300 Commit: 326f6e68b2 Workload version: 8.0.300-manifests.5273bb1c MSBuild version: 17.10.4+10fbfbf2e Среда выполнения: OS Name: Windows OS Version: 10.0.22631 OS Platform: Windows RID: win-x64 Base Path: C:\Program Files\dotnet\sdk\8.0.300\ Установленные рабочие нагрузки .NET: [maccatalyst] Источник установки: VS 17.10.35004.147, VS 17.10.35004.147 Версия манифеста: 17.2.8053/8.0.100 Путь к манифесту: C:\Program Files\dotnet\sdk-manifests\8.0.100\microsoft.net.sdk.maccatalyst\17.2.8053\WorkloadManifest.json Тип установки: FileBased [ios] Источник установки: VS 17.10.35004.147, VS 17.10.35004.147 Версия манифеста: 17.2.8053/8.0.100 Путь к манифесту: C:\Program Files\dotnet\sdk-manifests\8.0.100\microsoft.net.sdk.ios\17.2.8053\WorkloadManifest.json Тип установки: FileBased [android] Источник установки: VS 17.10.35004.147, VS 17.10.35004.147 Версия манифеста: 34.0.95/8.0.100 Путь к манифесту: C:\Program Files\dotnet\sdk-manifests\8.0.100\microsoft.net.sdk.android\34.0.95\WorkloadManifest.json Тип установки: FileBased [maui-windows] Источник установки: VS 17.10.35004.147, VS 17.10.35004.147 Версия манифеста: 8.0.40/8.0.100 Путь к манифесту: C:\Program Files\dotnet\sdk-manifests\8.0.100\microsoft.net.sdk.maui\8.0.40\WorkloadManifest.json Тип установки: FileBased [wasm-tools] Источник установки: VS 17.10.35004.147, VS 17.10.35004.147 Версия манифеста: 8.0.5/8.0.100 Путь к манифесту: C:\Program Files\dotnet\sdk-manifests\8.0.100\microsoft.net.workload.mono.toolchain.current\8.0.5\WorkloadManifest.json Тип установки: FileBased [aspire] Источник установки: VS 17.10.35004.147, VS 17.10.35004.147 Версия манифеста: 8.0.0/8.0.100 Путь к манифесту: C:\Program Files\dotnet\sdk-manifests\8.0.100\microsoft.net.sdk.aspire\8.0.0\WorkloadManifest.json Тип установки: FileBased Host: Version: 8.0.5 Architecture: x64 Commit: 087e15321b .NET SDKs installed: 3.1.426 [C:\Program Files\dotnet\sdk] 5.0.101 [C:\Program Files\dotnet\sdk] 5.0.201 [C:\Program Files\dotnet\sdk] 5.0.408 [C:\Program Files\dotnet\sdk] 6.0.202 [C:\Program Files\dotnet\sdk] 6.0.321 [C:\Program Files\dotnet\sdk] 8.0.300 [C:\Program Files\dotnet\sdk] .NET runtimes installed: Microsoft.AspNetCore.All 2.1.15 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All] Microsoft.AspNetCore.All 2.1.17 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All] Microsoft.AspNetCore.All 2.2.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All] Microsoft.AspNetCore.App 2.1.15 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 2.1.17 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 2.2.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 3.0.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 3.1.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 3.1.15 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 3.1.19 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 3.1.23 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 3.1.29 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 5.0.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 5.0.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 5.0.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 5.0.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 5.0.10 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 6.0.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 6.0.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 6.0.26 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 6.0.30 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 7.0.19 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 8.0.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.NETCore.App 2.1.15 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 2.1.17 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 2.2.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 3.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 3.1.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 3.1.15 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 3.1.19 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 3.1.23 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 3.1.29 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 5.0.1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 5.0.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 5.0.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 5.0.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 5.0.10 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 6.0.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 6.0.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 6.0.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 6.0.10 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 6.0.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 6.0.15 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 6.0.26 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 6.0.30 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 6.0.31 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 7.0.19 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 8.0.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.WindowsDesktop.App 3.1.15 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 3.1.19 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 3.1.23 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 3.1.29 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 5.0.1 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 5.0.4 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 5.0.6 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 5.0.9 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 5.0.10 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 6.0.4 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 6.0.5 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 6.0.9 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 6.0.10 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 6.0.15 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 6.0.26 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 6.0.30 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 6.0.31 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 7.0.19 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 8.0.5 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Other architectures found: arm64 [C:\Program Files\dotnet] registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\arm64\InstallLocation] x86 [C:\Program Files (x86)\dotnet] registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation] Environment variables: Not set global.json file: Not found

Other information

No response

joperezr commented 3 months ago

Interesting, I'd expect this to work given the logger field is protected so for some reason our source generator is not finding it. @xakep139 might be interesting to take a look here.

@ValeriyGourov just curious, is there a reason why you want to have the logger field be protected as opposed to having individual private loggers in each class? I think typically that is more common as people tend to want to have the logger T type to represent the class that is generating the logs, so in this case most people would want to have a private ILogger<Derived> _logger field instead so that the logs more easily show where the logs are coming from.

ValeriyGourov commented 3 months ago

@ValeriyGourov just curious, is there a reason why you want to have the logger field be protected as opposed to having individual private loggers in each class? I think typically that is more common as people tend to want to have the logger T type to represent the class that is generating the logs, so in this case most people would want to have a private ILogger<Derived> _logger field instead so that the logs more easily show where the logs are coming from.

@joperezr You are right about showing where the logs come from. But when we use the protected field _logger in the Derived class, it is of type ILogger<Derived> and not ILogger<Base>, right? 🤔 In this situation, we know exactly where each log event came from. And I don't want to repeat the ILogger<T> field in every derived class because I can use a single field from base class. 😎

joperezr commented 3 months ago

You are correct, somehow I missed that 😄

dariusclay commented 1 month ago

@joperezr this seems related to #5332