khellang / Scrutor

Assembly scanning and decoration extensions for Microsoft.Extensions.DependencyInjection
MIT License
3.61k stars 236 forks source link

Calling AddApplicationInsightsTelemetry() after .Decorate<,> removes TelemetryClient from service collection #233

Open Simkortet opened 2 days ago

Simkortet commented 2 days ago

I'm experiencing a strange issue in my projects after upgrading package version from 4.2.2 to 5.0.1.

I created the basic weather app web application template to replicate:

using Microsoft.ApplicationInsights;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

builder.Services.AddScoped<IFake, FakeService>();
builder.Services.Decorate<IFake, FakeDecorateService>();

builder.Services.AddApplicationInsightsTelemetry();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

var summaries = new[]
{
    "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

app.MapGet("/weatherforecast", (IFake fakeService, TelemetryClient telemetryClient) =>
    {
        var forecast = Enumerable.Range(1, 5).Select(index =>
                new WeatherForecast
                (
                    DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
                    Random.Shared.Next(-20, 55),
                    summaries[Random.Shared.Next(summaries.Length)]
                ))
            .ToArray();
        return forecast;
    })
    .WithName("GetWeatherForecast")
    .WithOpenApi();

app.Run();

record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
{
    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}

public interface IFake
{
    int Something();
}

public class FakeService : IFake
{
    public int Something()
    {
        return 1;
    }
}

public class FakeDecorateService(IFake fakeService) : IFake
{
    public int Something()
    {
        return fakeService.Something();
    }
}

Calling the weather endpoint results in an exception because the TelemetryClient was not registered. Note that calling builder.Services.AddApplicationInsightsTelemetry(); before .Decorate<,> works.

khellang commented 1 day ago

Hmm. That's weird. It would be interesting to see what the contents of builder.Services looks like in the following spots:

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

< -- here -- >

builder.Services.AddScoped<IFake, FakeService>();
builder.Services.Decorate<IFake, FakeDecorateService>();

< -- here -- >

builder.Services.AddApplicationInsightsTelemetry();

< -- here -- >

var app = builder.Build();

results in an exception because the TelemetryClient was not registered.

What does the exception say? Which type is it trying to resolve, exactly?