12

I'm using FunctionsStartup in an Azure Functions project to setup IoC bindings. However, any logs created from an injected ILogger<T> aren't appearing when I run it in Azure.

I've created a very cutdown version with a brand new example project to demonstrate this...

https://github.com/dracan/AzureFunctionsLoggingIssue

The output of this is...

2020-04-03T20:20:35  Welcome, you are now connected to log-streaming service. The default timeout is 2 hours. Change the timeout with the App Setting SCM_LOGSTREAM_TIMEOUT (in seconds). 
2020-04-03T20:20:54.643 [Information] Executing 'TestQueueTriggerFunction' (Reason='New queue message detected on 'myqueue'.', Id=2f13c4c7-8a35-4614-a768-1c3fecea8c31)
2020-04-03T20:20:54.654 [Information] Start of function (this log works)
2020-04-03T20:20:54.655 [Information] End of function (this log also works)
2020-04-03T20:20:54.655 [Information] Executed 'TestQueueTriggerFunction' (Succeeded, Id=2f13c4c7-8a35-4614-a768-1c3fecea8c31)

Note that the log entry "This log doesn't appear!" in MyClass.DoSomething() doesn't appear.

Dan
  • 5,692
  • 3
  • 35
  • 66
  • Turns out that it is logging in the 'Invocation Details' and Application Insights - just not in the live log stream. – Dan Apr 05 '20 at 09:15
  • https://github.com/Azure/Azure-Functions/issues/1256#issuecomment-609368420 – Dan Apr 05 '20 at 09:25

3 Answers3

13

Looks like this is a known issue. To quote Microsoft's reply from Github:

This is another subtlety about how that console/debug log works in the portal. It only displays log messages if it knows they come from this function -- which means they match the category Function.{FunctionName}.User. The ILogger we pass in uses this category automatically but anything you log with an external logger will not use this. We do this so that you don't get flooded with background messages in this view -- and unfortunately it filters out your own custom logger as well.

I've got an issue tracking this with one potential workaround: Azure/azure-functions-host#4689 (comment).

Dan
  • 5,692
  • 3
  • 35
  • 66
1

quick example below - use ILoggerFactory instead of ILogger<>

public class LoggingTests
{
    ILogger _log;
    public LoggingTests(ILoggerFactory loggerFactory)
    {
        _log = loggerFactory.CreateLogger(this.GetType());
    }

    [FunctionName("LoggingTests")]
    public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req, ILogger log)
    {
        _log.LogInformation("LogInformation");
        _log.LogWarning("LogWarning");
        _log.LogDebug("LogDebug");
        _log.LogTrace("LogTrace");
        _log.LogError("LogError");
        _log.LogCritical("LogCritical");

        return new OkResult();
    }
}

also check log level in host.json file

{
  "version": "2.0",
  "logging": {
    "logLevel": {
      "default": "Trace"
    },
    "applicationInsights": {
      "samplingExcludedTypes": "Request",
      "samplingSettings": {
        "isEnabled": true
      }
    }
  },
}
pburczyn
  • 98
  • 1
  • 6
  • 3
    This should definitely be seen as a "workaround" rather than a solution though. This gets mentioned in the Github issue link I posted. This fix is okay if there are just a few custom classes in your functionapp project - but if you're referencing a shared assembly - it's not great that you have to go through changing all your ILoggers to ILoggerFactorys in a shared assembly just to get around this issue. – Dan Jun 27 '21 at 06:05
1

You just need to modify the host.json file

{
  "version": "2.0",
  "logging": {
    "logLevel": {
      "Some.Of.My.NameSpace": "Information"
    },
    "applicationInsights": {
      ...
    }
  }
}

Source: https://learn.microsoft.com/en-us/azure/azure-functions/functions-dotnet-dependency-injection#iloggert-and-iloggerfactory

Tod
  • 2,070
  • 21
  • 27