6

Our function delegates all the logic to another class "CreateHandler" where we use the ILogger through DI. The function logs properly but the CreateHandler does not. Locally we verified that it does not log to the console, UNLESS we change the class namespace to something that starts with "Function". That means that FunctionR or FunctionS will work but RFunction or SFunction won't. We are dealing with that class and a service. Clearly our service has a completely different namespace and we would need to keep that one, while logging at the same time. How can we make the class log without changing the namespace?

CreateHandler class (logging right):

using ExampleProject.Domain.Entities;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;

namespace FunctionAnything
{
    public class CreateHandler
    {
        private readonly ILogger<CreateHandler> _logger;

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

        public async Task Handle(Car car)
        {
            _logger.LogInformation($"This is logging properly");
        }
    }
}

CreateHandler class (not logging):

using ExampleProject.Domain.Entities;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;

namespace ExampleProject.Functions.Handlers
{
    public class CreateHandler
    {
        private readonly ILogger<CreateHandler> _logger;

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

        public async Task Handle(Car car)
        {
            _logger.LogInformation($"This is not logging");
        }
    }
}

Startup:

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

[assembly: FunctionsStartup(typeof(ExampleProject.Functions.Startup))]
namespace ExampleProject.Functions
{
    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.AddSingleton<CreateHandler>();
        }
    }
}

Function:

using ExampleProject.Domain.Entities;
using ExampleProject.Functions.Handlers;
using ExampleProject.Service.Constants;
using Microsoft.Azure.WebJobs;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;

namespace ExampleProject.Functions
{
    public class Function
    {
        private readonly CreateHandler _createHandler;

        public Function(
            CreateHandler createHandler)
        {
            _createHandler = createHandler;
        }
        
        [FunctionName("Create")]
        public async Task Create([QueueTrigger(QueueNames.Create)] Car car)
        {
            log.LogInformation("I'm logged");
            await _createHandler.Handle(car);
        }
    }
}

local.settings.json

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true"
  }
}

host.json:

{
  "version": "2.0",
}
Ivan Glasenberg
  • 29,865
  • 2
  • 44
  • 60
user33276346
  • 1,501
  • 1
  • 19
  • 38
  • Can you share the relevant code where the logging happens and how the ILogger is injected? – Noah Stahl Aug 07 '20 at 14:36
  • @NoahStahl done ✔ – user33276346 Aug 07 '20 at 14:45
  • Looks good comparing with mine. On the application insights blade of your functions app in the portal, do you see "Application Insights is linked through Instrumentation Key in app settings"? – Noah Stahl Aug 07 '20 at 15:32
  • We have the APPINSIGHTS_INSTRUMENTATIONKEY setting with a value. But as far as I understand, that is only for the deployed function. I'm first trying to make it work locally. – user33276346 Aug 07 '20 at 15:38
  • @NoahStahl More testing reveals something more weird, it logs if the namespace starts with Function, that means that it will work with FunctionSomething, but won't with UFunction – user33276346 Aug 07 '20 at 16:08
  • Weird, I can say I have the same type of setup with a DI-injected service class that handles function logic from a different namespace. Is it the case that you can reproduce this by starting with a vanilla function from template and it breaks only when namespace is changed? – Noah Stahl Aug 07 '20 at 21:54
  • Yes, I did and it breaks. Does your service by any chance start with the word Function?Like FunctionSomething? If so, change that to anything else and see if it logs. I tried with a new template and didn't work either. – user33276346 Aug 07 '20 at 22:12
  • Neither my namespace or class have "Function" prefix. Maybe worth raising an issue in the app insights or functions SDK github repos.... – Noah Stahl Aug 07 '20 at 23:47

1 Answers1

6

I noticed this issue in github before(if the namespace is not started with Function), but currently cannot find it.

The solution is that, you should add the completed namespace+class name in host.json if the namespace is not started with Function. Like below:

{
  "version": "2.0",
  "logging": {
    "logLevel": {
      "ExampleProject.Functions.Handlers.CreateHandler": "Information"
    }
  }
}

Or a general way:

"logLevel": { "Default": "Information" }
Ivan Glasenberg
  • 29,865
  • 2
  • 44
  • 60