How To Start Logging With Serilog
New 2.0.14
Info
This document applies to Nodinite Serilog sinks versions >= 2.0.14 and assumes you use the isolated worker model with Azure Functions using .NET 8 or later.
If you want to log using the Microsoft.Extensions.Logging.ILogger, see 'How To Start Logging With Microsoft.Extensions.Logging.ILogger in Azure Functions'.
You can use different settings examples (appsettings.json); the rest of the code examples below are the same regardless of which method you choose.
- Required NuGet packages
- Dependencies in Project (.csproj)
- Startup file (Program.cs)
- Log (Function.cs)
- appsettings.json
Info
The Settings section is documented on a shared page. Read more at here
Required NuGet packages
To enable Serilog Logging, add the required NuGet packages to your project. You can do this using the NuGet Package Manager in Visual Studio or by editing the .csproj file directly:
- Nodinite.Serilog.AzureBlobStorageSink (if you use the Blob sink, choose any other Nodinite sink you like)
- Serilog.Settings.Configuration
Dependencies in Project (.csproj)
Update the version when you update the NuGet packages. The versions below are examples. Always update to the latest version.
<ItemGroup>
...
<PackageReference Include="Nodinite.Serilog.AzureBlobStorageSink" Version="2.0.27" />
<PackageReference Include="Serilog.Settings.Configuration" Version="8.0.2" />
</ItemGroup>
Startup file (Program.cs)
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog;
using Serilog.Core;
var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults()
.ConfigureServices((context, services) =>
{
// Create configuration object and read settings
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
// Create the logger object
var logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.CreateLogger();
// Register the logger object as a singleton using dependency injection to achieve great performance when you write multiple logs
services.AddSingleton<Serilog.ILogger, Serilog.Core.Logger>(sp => logger);
})
.Build();
host.Run();
Log (Function.cs)
Inject the Logger inside the constructor instead of the method level.
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
using Serilog.Core.Enrichers;
namespace Nodinite.Demo.Azure.Functions
{
public class Function1
{
private readonly Serilog.ILogger _logger;
public Function1(Serilog.ILogger logger)
{
_logger = logger;
}
[Function("Function1")]
public HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req)
{
#region Nodinite Serilog sample code (should be refactored into a reusable component injected using dependency injection; all part of your documented asynchronous Logging Strategy)
string payload = await new StreamReader(req.Body).ReadToEndAsync();
string correlationId = Guid.NewGuid().ToString();
if (req.Headers.TryGetValue("x-ms-client-tracking-id", out Microsoft.Extensions.Primitives.StringValues id))
{
correlationId = id[0];
}
_logger.ForContext(new PropertyEnricher("ApplicationInterchangeId", $"{correlationId}"))
.Enrich.WithProperty("Color", "Yellow")
.ForContext(new PropertyEnricher("Body", JsonConvert.SerializeObject(payload)))
.ForContext(new PropertyEnricher("OriginalMessageType", "OrderMessage#1.0"))
.Information("Hello from Function");
#endregion
var response = req.CreateResponse(HttpStatusCode.OK);
response.Headers.Add("Content-Type", "text/plain; charset=utf-8");
response.WriteString("Welcome to Azure Functions!");
return response;
}
}
}
appsettings.json
Depending on the type of sink you use, apply the appropriate configuration using any of the following
- How To Start Logging With Serilog
Blob
đź’ˇAuthentication and connection options for for Azure Blob Storage (recommended option!).
Blob (Using the default Managed Identity)
{
"Serilog": {
"Using": ["Nodinite.Serilog.AzureBlobStorageSink"],
"WriteTo": [
{
"Name": "AzureBlobStorageSink",
"Args": {
"StorageAccountName": "acme",
"ContainerName": "logevents",
"Settings": {
...
}
}
}
]
}
}
Blob (Using an explicit Managed Identity)
New 2.0.16
{
"Serilog": {
"Using": ["Nodinite.Serilog.AzureBlobStorageSink"],
"WriteTo": [
{
"Name": "AzureBlobStorageSink",
"Args": {
"StorageAccountName": "acme",
"ContainerName": "logevents",
"ManagedIdentityClientId": "00000000-0000-0000-0000-000000000000",
"Settings": {
...
}
}
}
]
}
}
Blob (Using a Connection string)
Copy the ConnectionString from the Azure Portal (Access keys) for the Storage Account in use.
{
"Serilog": {
"Using": [ "Nodinite.Serilog.AzureBlobStorageSink" ],
"WriteTo": [
{
"Name": "NodiniteAzureBlobStorageSinkWithConnectionString",
"Args": {
"ConnectionString": "DefaultEndpointsProtocol=https;AccountName=acme;AccountKey=xyz;EndpointSuffix=core.windows.net",
"ContainerName": "logevents",
"Settings": {
...
}
}
}
]
}
}
Event Hub
đź’ˇAuthentication and connection options for for Azure Event Hub.
Event Hub (Using Managed Identity)
{
"Serilog": {
"Using": ["Nodinite.Serilog.EventHubSink"],
"WriteTo": [
{
"Name": "NodiniteEventHubSink",
"Args": {
"eventHubNameSpace": "acme.servicebus.windows.net",
"eventHubName": "eventhub-01",
"Settings": {
...
}
}
}
]
}
}
Event Hub (Using a Connection string)
Use a dedicated Shared access policy to create a connectionstring including the EntityPath=%name%
.
{
"Serilog": {
"Using": [ "Nodinite.Serilog.EventHubSink" ],
"WriteTo": [
{
"Name": "NodiniteEventHubSink",
"Args": {
"ConnectionString": "Endpoint=sb://xyz.servicebus.windows.net/;SharedAccessKeyName=Default;SharedAccessKey=secretstuff;EntityPath=yourentityname
",
"Settings": {
...
}
}
}
]
}
}
File
đź’ˇConnection options for for SMB Shares and Folders.
{
"Serilog": {
"Using": [ "Nodinite.Serilog.FileSink" ],
"WriteTo": [
{
"Name": "NodiniteFileSink",
"Args": {
"Folder": "\\FancyUNCSrv01\\DaShare\\In",
"Settings": {
...
"FileExtension": ".json"
}
}
}
]
}
}
Log API
{
"Serilog": {
"Using": [ "<placeholder>" ],
"WriteTo": [
{
"Name": "NodiniteApiSink",
"Args": {
"NodiniteApiUrl": "https://fancysrv01/nodinite/dev/logapi/",
"Settings": {
...
}
}
}
]
}
}
Service Bus
đź’ˇAuthentication and connection options for for Azure Service Bus.
Service Bus (Using the default Managed Identity)
{
"Serilog": {
"Using": ["Nodinite.Serilog.ServiceBusSink"],
"WriteTo": [
{
"Name": "NodiniteServiceBusSink",
"Args": {
"NamespaceName": "acme.servicebus.windows.net",
"QueueName": "sbq01",
"Settings": {
...
}
}
}
]
}
}
Service Bus (Using an explicit Managed Identity)
New 2.0.27
{
"Serilog": {
"Using": ["Nodinite.Serilog.ServiceBusSink"],
"WriteTo": [
{
"Name": "NodiniteServiceBusSink",
"Args": {
"NamespaceName": "acme.servicebus.windows.net",
"QueueName": "sbq01",
"ManagedIdentityClientId": "00000000-0000-0000-0000-000000000000",
"Settings": {
...
}
}
}
]
}
}
Service Bus (Using a Connection string)
Copy the ConnectionString from the Azure Portal (Access keys) for the Storage Account in use.
{
"Serilog": {
"Using": [ "Nodinite.Serilog.ServiceBusSink" ],
"WriteTo": [
{
"Name": "NodiniteServiceBusSinkWithConnectionString",
"Args": {
"ConnectionString": "DefaultEndpointsProtocol=https;AccountName=acme;AccountKey=xyz;EndpointSuffix=core.windows.net",
"QueueName": "sqb01",
"Settings": {
...
}
}
}
]
}
}
Advanced settings using multiple sinks
In this example multiple sinks are used. The example uses the Azure Blob Storage Sink and the Service Bus Sink. The settings for each sink are specified in the Settings section of the configuration file.
{
"Serilog": {
"Using": [ "Nodinite.Serilog.AzureBlobStorageSink", "Nodinite.Serilog.ServiceBusSink" ],
"WriteTo": [
{
"Name": "AzureBlobStorageSink",
"Args": {
"StorageAccountName": "acme",
"ContainerName": "logevents",
"Settings": {
...
}
}
},
{
"Name": "NodiniteServiceBusSink",
"Args": {
"NamespaceName": "acme.servicebus.windows.net",
"QueueName": "sbq01",
"Settings": {
...
}
}
},
{
"Name": "Console",
"Args": {
"theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}"
}
}
]
}
}
Next Step
âť”'How To Start Logging With Microsoft.Extensions.Logging.ILogger in Azure Functions'
PickupService
Log Events
JSON Log Event