Kinexus
Kinexus

Reputation: 12904

ILogger<TCategoryName> is never null in api controller

I have been looking to integrate Serilog into a new API implementation using net core 5. The way I understand this to work is that it overrides the basic ILogger implementation and adds further functionality, which is all good and works as expected.

The issue I am having is that even without specifying a logging implementation in my startup, the ILogger dependancy on controllers is never null. While this might be a strange question to ask, I am looking to understand where this default instance of ILogger is coming from.

The problem can be reproduced by creating a new net core 5 API in Visual Studio, whereby get an example Weather controller and a single Get() method. This example controller has an ILogger dependency in the constructor as below;

 public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
        }

Which can then used in the Action;

 [HttpGet]
        public IEnumerable<WeatherForecast> Get()
        {
            _logger.LogInformation("Testing");

            var rng = new Random();
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = rng.Next(-20, 55),
                Summary = Summaries[rng.Next(Summaries.Length)]
            })
            .ToArray();
        }

The sample gives the following program.cs and startup.cs;

  public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {

            services.AddControllers();
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "WebApplication2", Version = "v1" });
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseSwagger();
                app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "WebApplication2 v1"));
            }

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }

 public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }

Nowhere in this code do we appear to be adding/defining Logger and I am trying to understand where this comes from.

In my own implementation, I have a dependency on ILogger within other classes which works in the context of being called from the API, but fails when being called via a unit test as (at present) I am not explicitly defining ILogger within the fixture.

So where does the ILogger get initialized within the example API?

Examples of other APIs have the following code in the constructor, but if logger is never null, then.....

 _logger = logger ?? throw new ArgumentNullException(nameof(logger));

Upvotes: 0

Views: 295

Answers (1)

gjhommersom
gjhommersom

Reputation: 179

Calling Host.CreateDefaultBuilder adds defaults for logging. To remove those defaults you can do this:

Host.CreateDefaultBuilder(args)
  .ConfigureLogging(logging =>
  {
    logging.ClearProviders();
    // Add your own logging provider here.
  })

More details can be found here: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-5.0

Upvotes: 1

Related Questions