ILogger injected via constructor for Http trigger functions with Azure Function 2.x

Calling LogCategories.CreateFunctionUserCategory fixed my problem. Complete example:

Azure Functions Core Tools (2.7.1158 Commit hash: f2d2a2816e038165826c7409c6d10c0527e8955b)
Function Runtime Version: 2.0.12438.0

Startup.cs

No need to add builder.Services.AddLogging(); it's imported automatically in the container.

using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;

[assembly: FunctionsStartup(typeof(MyFunctionsNamespace.Startup))]

namespace MyFunctionsNamespace
{
    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.AddTransient<IMyService, MyService>();
        }
    }
}

MyFunkyFunction.cs

using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;

namespace MyFunctionsNamespace
{
    public class MyFunkyFunction
    {
        private readonly IMyService _myService;

        public MyFunkyFunction(IMyService myService)
        {
            _myService = myService;
        }

        [FunctionName("FunkyFunc")]
        public async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
            HttpRequest req
            , ILogger log
        )
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            _myService.Do();

            return new OkObjectResult("Hello");
        }
    }
}

IMyService.cs

Anything in LogCategories.CreateFunctionUserCategory will do the job. It seems to be some WebJob legacy requirement.

using Microsoft.Azure.WebJobs.Logging;
using Microsoft.Extensions.Logging;

namespace MyFunctionsNamespace
{
    public interface IMyService
    {
        void Do();
    }


    public class MyService : IMyService
    {
        private readonly ILogger _log;

        public MyService(ILoggerFactory loggerFactory)
        {
            // Important: Call CreateFunctionUserCategory, otherwise log entries might be filtered out
            // I guess it comes from Microsoft.Azure.WebJobs.Logging
            _log = loggerFactory.CreateLogger(LogCategories.CreateFunctionUserCategory("Common"));
        }

        public void Do()
        {
            _log.Log(LogLevel.Information, "Hello from MyService");
        }
    }
}

I had this problem as well. I was able to fix it by calling AddLogging():

[assembly: WebJobsStartup(typeof(Startup))]
namespace MyApp
{
    public class Startup : IWebJobsStartup
    {
        public void Configure(IWebJobsBuilder builder)
        {
            builder.Services.AddHttpClient();
            builder.Services.AddTransient<IAppSettings, AppSettings>();     
            builder.Services.AddLogging();
        }
}

And then, in the Azure Function, I had to do pass a ILoggerFactory instead of an ILogger and get the ILogger instance from the loggerFactory:

public class Functions
{
    private HttpClient _httpClient;
    private IAppSettings _appSettings;
    private ILogger _log;

    public Functions(HttpClient httpClient, IAppSettings appSettings, ILoggerFactory loggerFactory)
    {
        _log = loggerFactory.CreateLogger<Functions>();
    }

    [FunctionName("Token")]
    public async Task<IActionResult> Token(
        [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "Token")]
        HttpRequest httpRequest)
    {
           // No need to keep getting the ILogger from the Run method anymore :)
    }
}

I had this same problem. I finally found that adding this "logging" element to my host.json file solved it for me.

{
    "version": "2.0",
    "logging": {
        "logLevel": {
            "default": "Trace"
        }
    }
}

Now the standard .NET core constructor-injected logger method works fine.