Search code examples
c#azure-functionsserilogserilog-sinks-file

Adding Serilog to Azure Function App and logging to a file?


I am trying to add Serilog to an Azure Function app (.Net 6.0) and of course its not writing to a file. When I run the program, I can see in the console '[15:58:00 INF] Hello World!'. So then why not to the file? My other question is why do I see '[16:03:24 INF] null'? My long term goal is to log to a blob on Azure. Thank you for your help.

using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using Serilog;
using Serilog.Events;
using Serilog.Extensions.Logging;
using SerilogFunctionApp;
using ILogger = Microsoft.Extensions.Logging.ILogger;

[assembly: WebJobsStartup(typeof(Startup))]

namespace SerilogFunctionApp
{
  public class Startup : IWebJobsStartup
  {
    public void Configure(IWebJobsBuilder builder)
    {
      string basedir = AppDomain.CurrentDomain.BaseDirectory;

      Log.Logger = new LoggerConfiguration()
          .MinimumLevel.Information()
          .WriteTo.Console()
          .WriteTo.Debug()
          .WriteTo.File(basedir + "/logs/log-.txt", rollingInterval: RollingInterval.Day, rollOnFileSizeLimit: true)
        .CreateLogger();

      builder.Services.AddLogging(lb => { lb.AddSerilog(Log.Logger, true); });
    }
  }

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

    public Function1(ILoggerFactory loggerFactory)
    {
      _log = loggerFactory.CreateLogger<Function1>();
    }
    
    [FunctionName("Function1")]
    public void Run([TimerTrigger("0 */1 * * * *")] TimerInfo myTimer, ILogger log)
    {
      _log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");

      Log.Information("Hello World!");
    }
  }
}

I found a StackOverflow about adding the Startup to a function which looked different that what I posted aboved so I tried modified my app and still there's no logging to the file.

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Azure.WebJobs;
using Serilog;
using ILogger = Microsoft.Extensions.Logging.ILogger;

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

namespace SerilogFunctionApp
{
  public class Startup : FunctionsStartup
  {
    public override void ConfigureAppConfiguration(IFunctionsConfigurationBuilder builder)
    {
      var context = builder.GetContext();

      //builder.ConfigurationBuilder
      //  .AddJsonFile(Path.Combine(context.ApplicationRootPath, "appsettings.json"), optional: true, reloadOnChange: false)
      //  .AddJsonFile(Path.Combine(context.ApplicationRootPath, $"appsettings.{context.EnvironmentName}.json"), optional: true, reloadOnChange: false);

    }
    public override void Configure(IFunctionsHostBuilder builder)
    {
      // get the configuration from the builder
      var configuration = builder.GetContext().Configuration;

      string basedir = AppDomain.CurrentDomain.BaseDirectory;

      Log.Logger = new LoggerConfiguration()
        .MinimumLevel.Information()
        .WriteTo.Console()
        .WriteTo.Debug()
        .WriteTo.File(basedir + "/logs/log-.txt", rollingInterval: RollingInterval.Day, rollOnFileSizeLimit: true)
        .CreateLogger();

      builder.Services.AddLogging(lb => { lb.AddSerilog(Log.Logger, true); });
    }
  }

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

    public Function1(ILoggerFactory loggerFactory)
    {
      _log = loggerFactory.CreateLogger<Function1>();
    }
    
    [FunctionName("Function1")]
    public void Run([TimerTrigger("0 */1 * * * *")] TimerInfo myTimer, ILogger log)
    {
      _log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");

      Log.Information("Hello World!");
    }
  }

Solution

  • I have reproduced in my local environment a example, You can use normal Timer Trigger function write logs into a file by following below workaround: Firstly create a Azure Function App with timer trigger then in host.json file add fileLoggingMode as below:

    {
      "version": "2.0",
      "logging": {
        "fileLoggingMode": "always",
        "applicationInsights": {
          "samplingSettings": {
            "isEnabled": true,
            "excludedTypes": "Request"
          }
        }
      }
    }
    

    Then in Function.cs classs:

    using System;
    using Microsoft.Azure.WebJobs;
    using Microsoft.Azure.WebJobs.Host;
    using Microsoft.Extensions.Logging;
    
    namespace FunctionApp18
    {
        public class Function1
        {
            [FunctionName("Function1")]
            public void Run([TimerTrigger("0 */1 * * * *")]TimerInfo myTimer, ILogger log)
            {
                log.LogInformation("Rithwik Here");
                log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
            }
        }
    }
    

    I get the logs in console as:

    enter image description here

    Then in my local at this path:

    %temp%\LogFiles\Application\Functions.
    

    I can find my logs are written to a file as below:

    enter image description here