IntoNET
IntoNET

Reputation: 504

SeriLog and Azure Functions Isolated Worked Model not logging

I am creating some basic Azure Functions using the Isolated Worker model for learning purposes. My go-to logging framework is the excellent Serilog, but despite having used it many times I cannot get it to log in my solution.

Here is the Program.cs file in it's entirety

using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog;

namespace fsefunctions;

public class Program
{
    static async Task Main(string[] args)
    {
        Log.Logger = new LoggerConfiguration()
          .WriteTo.Console()
          .WriteTo.Seq(serverUrl: "http://REDACTEDSEQURL")
          .Enrich.FromLogContext()
          .CreateLogger();

        var host = new HostBuilder()
            .ConfigureFunctionsWebApplication()
            .ConfigureLogging(l => { l.AddSerilog(Log.Logger, true); })
            .ConfigureServices(s =>
                {
                    s.AddOptions<AppSettings>().Configure<IConfiguration>((settings, configuration) =>
                    {
                        configuration.GetSection("FseApi").Bind(settings);
                    });
                })
            .ConfigureAppConfiguration(c =>
                {
                    c.AddJsonFile("appsettings.json", optional: true, reloadOnChange: false);
                    c.AddEnvironmentVariables();
                })
            .Build();

        Log.Information("fsefunctiobs.program started at " + DateTime.UtcNow);

        await host.RunAsync();
    }
}

And here is a simple TimerTrigger class that puts some text in an Azure ServiceBus queue.

using System;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;

namespace fsefunctions;

public class MakeRequest
{
    private readonly ILogger<MakeRequest> log;

    public MakeRequest(ILogger<MakeRequest> log)
    {
        this.log = log;
    }

    [Function("MakeRequest")]
    [ServiceBusOutput("servicerequests")]
    public string Run([TimerTrigger("0/3 * * * * *")] TimerInfo myTimer, FunctionContext context)
    {
        log.LogInformation($"MakeRequest function executed at: {DateTime.UtcNow}");

        try
        {
            return $"New message item at {DateTime.UtcNow}";
        }
        catch (Exception e)
        {
            log.LogError($"MakeRequest raised exception {e.GetType()} with  message {e.Message} at {e.StackTrace}");
            return e.Message;
        }
    }
}

There's another one that reads a message from the queue, but it's not really relevant to this question. The two functions work perfectly, but produce no logging output.

Thanks!

Upvotes: 1

Views: 1092

Answers (1)

Ikhtesam Afrin
Ikhtesam Afrin

Reputation: 6487

I am able to log using Serilog in Azure Isolated function. You need to register it using .AddLogging in program.cs file.

My program.cs file looks like below-

using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog;
using Serilog.Core;

var host = new HostBuilder()
    .ConfigureFunctionsWebApplication()
    .ConfigureServices(services =>
    {
        services.AddApplicationInsightsTelemetryWorkerService();
        services.ConfigureFunctionsApplicationInsights();
        services.AddLogging(loggingBuilder =>
        {
            loggingBuilder.AddSerilog(new LoggerConfiguration().WriteTo.Console().CreateLogger());
        });
    })
    .Build();
host.Run();

Or you can add in this way too.

using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog;
using Serilog.Core;

var host = new HostBuilder()
    .ConfigureFunctionsWebApplication()
    .ConfigureServices(services =>
    {
        services.AddApplicationInsightsTelemetryWorkerService();
        services.ConfigureFunctionsApplicationInsights();
        var logger = new LoggerConfiguration()
        .WriteTo.Console()
        .CreateLogger();
        services.AddLogging(log =>
        {
            log.AddSerilog(logger, true);
        });
    })
    .Build();
host.Run();

.csproj file-

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <AzureFunctionsVersion>v4</AzureFunctionsVersion>
    <OutputType>Exe</OutputType>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <RootNamespace>_78030164</RootNamespace>
  </PropertyGroup>
  <ItemGroup>
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.21.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.1.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" Version="1.2.1" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Timer" Version="4.3.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.17.0" />
    <PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.22.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="1.2.0" />
    <PackageReference Include="Serilog" Version="3.1.2-dev-02097" />
    <PackageReference Include="Serilog.Extensions.Logging" Version="8.0.1-dev-10373" />
    <PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" />
    <PackageReference Include="Serilog.Sinks.File" Version="5.0.1-dev-00972" />
  </ItemGroup>
  <ItemGroup>
    <None Update="host.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="local.settings.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <CopyToPublishDirectory>Never</CopyToPublishDirectory>
    </None>
  </ItemGroup>
  <ItemGroup>
    <Using Include="System.Threading.ExecutionContext" Alias="ExecutionContext" />
  </ItemGroup>
</Project>

I have a timer trigger function with below code in it.

using System;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;

namespace _78030164
{
    public class Function1
    {
        private readonly ILogger _logger;

        public Function1(ILoggerFactory loggerFactory)
        {
            _logger = loggerFactory.CreateLogger<Function1>();
        }

        [Function("Function1")]
        public void Run([TimerTrigger("0 */5 * * * *")] TimerInfo myTimer)
        {
            _logger.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
            
            if (myTimer.ScheduleStatus is not null)
            {
                _logger.LogInformation($"Next timer schedule at: {myTimer.ScheduleStatus.Next}");
            }
        }
    }
}

I am able to get the expected response while executing the function.

enter image description here

Upvotes: 2

Related Questions