Reputation: 504
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
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.
Upvotes: 2