Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serilog in Azure Functions

Each method in Azure Functions can have a Microsoft.Extensions.Logging.ILogger injected into it for logging. Using WebJobsStartup with a startup class you can change the logging to use Serilog using the following syntax:

[assembly: WebJobsStartup(typeof(Startup))]
namespace MyFuncApp {
    public class Startup : IWebJobsStartup
    {
        public void Configure(IWebJobsBuilder builder)
        {
            builder.Services.AddLogging(
                lb => lb.ClearProviders()
                    .AddSerilog(
                        new LoggerConfiguration()
                            .Enrich.FromLogContext()
                            .WriteTo.Console()
                            .WriteTo.File(@"C:\Temp\MyFuncApp.log")
                            .CreateLogger(),
                        true));
        }
    }
}

I can also add other objects to the DI and inject them either into the methods or into the constructor for the class containing the methods using i.e. builder.Services.AddSingleton<IMyInterface, MyImplementation>();

However, I would very much like to be able to inject the Microsoft.Extensions.Logging.ILogger in the same way, but if I try to use the ILogger in the constructor I get the following error during method invokation (as that's when the class is created):

Microsoft.Extensions.DependencyInjection.Abstractions: Unable to resolve service for type 'Microsoft.Extensions.Logging.ILogger' while attempting to activate 'MyFuncApp.MyFunctions'.

So, is there any way of injecting the ILogger into a class constructor like this?

public class MyFunctions
{
    private IMyInterface _myImpl;
    private ILogger _log;

    public MyFunctions(
        IMyInterface myImplememtation, // This works
        ILogger log) // This does not
    {
        _myImpl = myImplementation;
        _log = log;
        _log.LogInformation("Class constructed");
    }

    public async Task<IActionResult> Function1([HttpTrigger() ... ) {
        _log.LogInformation("Function1 invoked");
    }
}
like image 907
GTHvidsten Avatar asked Apr 30 '19 08:04

GTHvidsten


People also ask

What is Serilog used for?

Serilog is a . NET library that provides diagnostic logging to files, the console, and almost everywhere you would like. Serilog can be used in classic . NET Framework applications and for applications running on the latest and greatest .

What is Serilog C#?

Serilog is a logging library for . NET and C# that allows for more detailed and structured logging than the default . NET logging library. Serilog can be used to log information about application events, errors, and performance metrics.

Can you stop logging with Serilog?

For example, if you are using Serilog you should configure Log. Logger and LibLog will use it. Also you can disable logging by setting LogProvider. IsDisabled to true . "


3 Answers

It is possible to further simplify the necessary setup by using the package Anotar.Serilog.Fody (and any other Anotar package for that matter)

You need to set up Serilog all the same in the Startup class.

However, with the Fody package you can completely get rid of the injected logger

using Anotar.Serilog;

public class Functions
{
    [FunctionName("Token")]
    public async Task<IActionResult> Function1(
        [HttpTrigger()]...)
    {
        // static calls to the LogTo class
        // get translated into proper Serilog code during build
        LogTo.Information("Function1 invoked");
    }
}
like image 200
Tomasz Pluskiewicz Avatar answered Oct 03 '22 23:10

Tomasz Pluskiewicz


Please try the code below, it works at my side:

    [assembly: WebJobsStartup(typeof(Startup))]
    namespace MyApp
 {
        public class Startup : IWebJobsStartup
        {
            public void Configure(IWebJobsBuilder builder)
            {
                //other code

                builder.Services.AddLogging();
            }
        }



    public class Functions
    {
        //other code
        private ILogger _log;

        public Functions(ILoggerFactory loggerFactory)
        {
            _log = loggerFactory.CreateLogger<Functions>();
        }

        [FunctionName("Token")]
        public async Task<IActionResult> Function1(
            [HttpTrigger()]...)
        {
               _log.LogInformation("Function1 invoked");
        }
    }

}
like image 25
Ivan Yang Avatar answered Oct 04 '22 00:10

Ivan Yang


With AzureFunctions v3, the pattern you outlined in your question works out-of-the box.

like image 31
Daniel Avatar answered Oct 04 '22 01:10

Daniel