I've created a simple Azure Function with the intension of using Serililog for logging to Azure Blob Storage.
When using inline configuration for the Serilog sink, that works perfectly fine, the sink is created and Serilog happily wirtes to Blob storage.
This works:
Log.Logger = new LoggerConfiguration()
.WriteTo.AzureBlobStorage(
"STORAGEACCOUNT CONNECTION STRING", // <-- inline config
LogEventLevel.Information,
null,
"{yyyy}/{MM}/{dd}/MyLogFile.txt")
.CreateLogger();
The problem is that I would like to configure this all via appsettings.json
, but when I try this (both locally running in the emulator & in the cloud), it fails to bind the sink settings, and as a result its failing to log to to the Blog storage.
If I debug, I can see that the config values are being loaded as expected into the configuration
object, but they are not being applied to the logging configuration.
This doesnt work:
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.CreateLogger();
appsettings.json
in this snippet:
{
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Information"
}
},
"WriteTo": [{
"Name": "AzureBlobStorage",
"Args": {
"connectionString": " --- REPLACE WITH STORAGEACCOUNT BLOB CONNECTION STRING --- ",
"formatter": "Serilog.Formatting.Compact.RenderedCompactJsonFormatter, Serilog.Formatting.Compact",
"storageFileName": "{yyyy}/{MM}/{dd}/MyLogFile.txt",
"retainedFileCountLimit": 31
}
}
],
"Properties": {
"Application": "int-test-logging",
"Environment": "int"
}
}
}
I'm not sure what I'm doing incorrectly but any help would be appreciated. The following github repo contains code to implement the above (both approaches), and reproduces this behaviour. https://github.com/oneiltomlinson/AzureFunctionsLogging
Just add
"Using": [ "Serilog.Sinks.AzureBlobStorage" ] //under Serilog Config
and it will work!
Working Config
{
"Serilog": {
"Using": [
"Serilog.Sinks.AzureBlobStorage"
],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Information"
}
},
"WriteTo": [
{
"Name": "AzureBlobStorage",
"Args": {
"connectionString": " --- REPLACE WITH STORAGEACCOUNT BLOB CONNECTION STRING --- ",
"formatter": "Serilog.Formatting.Compact.RenderedCompactJsonFormatter, Serilog.Formatting.Compact",
"storageFileName": "{yyyy}/{MM}/{dd}/MyLogFile.txt",
"retainedFileCountLimit": 31
}
}
],
"Properties": {
"Application": "int-test-logging",
"Environment": "int"
}
}
}
I've the same issue and even with all the required "using" of the used sinks, nothing change. This is my configuration file (just about the Serilog part):
"Serilog": {
"Using": [
"Serilog.Sinks.RollingFile",
"Serilog.Sinks.AzureTableStorage"
],
"MinimumLevel": "Information",
"Override": {
"Microsoft": "Warning",
"Microsoft.EntityFrameworkCore": "Information"
},
"WriteTo": [
{
"Name": "Logger",
"Args": {
"configureLogger": {
"MinimumLevel": "Information",
"WriteTo": [
{
"Name": "Console",
"outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff}] [{Level:u3}] [TID:{ThreadId}] - {Message:lj}{NewLine}{Exception}"
},
{
"Name": "Debug",
"outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff}] [{Level:u3}] [TID:{ThreadId}] - {Message:lj}{NewLine}{Exception}"
},
{
"Name": "AzureTableStorage",
"Args": {
"storageTableName": "HeroFunctionsLogs",
"connectionString": "DefaultEndpointsProtocol=https;AccountName=herobugari;AccountKey=NYJcdoCg9mQxqbQaTUdIxOHYQGdcKAwMsuWwzDub29UweHR1c+wd6Sh3IDQNB+eCx3DAe/ccobxu67sJvqQB5g==",
"outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff}] [{Level:u3}] [TID:{ThreadId}] - {Message:lj}{NewLine}{Exception}",
"restrictedToMinimumLevel": "Information",
"writeInBatches": true,
"batchPostingLimit": 100
}
},
{
"Name": "RollingFile",
"Args": {
"pathFormat": "logs\\Bulgari.Hero.Functions.log",
"retainedFileCountLimit": 10,
"buffered": true,
"flushToDiskInterval": 5,
"outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff}] [{Level:u3}] [TID:{ThreadId}] - {Message:lj}{NewLine}{Exception}"
}
}
],
"Filter": [
{
"Name": "ByExcludingOnly",
"Args": {
"expression": "SourceContext like '%Microsoft.EntityFrameworkCore%'"
}
}
]
}
}
}
]
}
and this the Startup.cs code that reads and try to use it:
var config = new ConfigurationBuilder()
.SetBasePath(Environment.CurrentDirectory)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables().Build();
// Registering Serilog provider
logger = new LoggerConfiguration()
//.WriteTo.Console()
//.WriteTo.File("logs\\herofunctions.log", rollingInterval: RollingInterval.Day)
.ReadFrom.Configuration(config)
.CreateLogger();
builder.Services.AddLogging(lb => lb.AddSerilog(logger));
The logger object has no "sinks" registered as it happens in the question.
I have solved exactly the same issue here by adding entries in local.settings.json.
"Serilog:Using:0": "Serilog.Sinks.Console",
"Serilog:MinimumLevel": "Information",
"Serilog:Override:Microsoft": "Warning",
"Serilog:Override:System": "Warning",
"Serilog:WriteTo:Console:Name": "Console"
then in StartUp.cs:
var provider = builder.Services.BuildServiceProvider();
var config = provider.GetRequiredService<IConfiguration>();
Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(config).CreateLogger();
then the function:
public class TestFunction
{
private readonly ILogger _logger;
public TestFunction()
{
_logger = Log.Logger;
}
[FunctionName("TestFunction")]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req)
{
_logger.Information("Hello");
return new OkResult();
}
}
}
I can see the config entries registered and entries are logged!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With