This is really strange. I have a simple example here.
Please note in the sample (linked above) I have:
public BlobLoggerProvider(BlobLoggerOptions options)
{
Options = options;
Options = new BlobLoggerOptions
{
Path = "log/{yyyy-MM-dd}.txt",
Interval = "day",
AzureStorage = "UseDevelopmentStorage=true"
};
Interval = GetInterval(Options.Interval);
Start();
}
This is setting explicit values for the Options so the system will run. The bug is the passed in parameter options
has null values for all properties.
I have one ILoggerProvider that works perfectly (in Blazor server). Defined as:
[ProviderAlias("File")]
public class FileLoggerProvider : LoggerProviderBase
{
protected FileLoggerOptions? Options;
public FileLoggerProvider(IOptionsMonitor<FileLoggerOptions> options) : this(options.CurrentValue)
{
SettingsChangeToken = options.OnChange(opt => { Options = opt; });
}
public FileLoggerProvider(FileLoggerOptions options)
{
Options = options;
Interval = GetInterval(options.Interval);
Start();
}
The other is defined as follows:
[ProviderAlias("Blob")]
public class BlobLoggerProvider : LoggerProviderBase
{
protected BlobLoggerOptions Options;
public BlobLoggerProvider(IOptionsMonitor<BlobLoggerOptions> options) : this(options.CurrentValue)
{
SettingsChangeToken = options.OnChange(opt => { Options = opt; });
}
public BlobLoggerProvider(BlobLoggerOptions options)
{
Options = options;
Start();
}
This second one passes in a BlobLoggerOptions
with all properties set to null.
And even weirder - if I change it to have a FileLoggerOptions
as the options passed in - it does populate that with the "File" properties from appSettings.json. Event though it has [ProviderAlias("Blob")]
.
Any idea what can be causing this? I've tried a ton of different things, all to no luck.
Below files in case they're helpful:
appSettings.json:
"Blob": {
"Path": "logs/{yyyy-MM-dd}.txt",
"Interval": "Day",
"AzureStorage": "UseDevelopmentStorage=true"
},
"File": {
"Path": "C:/temp/{yyyy-MM-dd}.txt",
"Interval": "day"
},
Properties files:
public class FileLoggerOptions
{
public string? Path { get; set; }
public string? Interval { get; set; }
}
internal class FileLoggerOptionsSetup : ConfigureFromConfigurationOptions<FileLoggerOptions>
{
public FileLoggerOptionsSetup(ILoggerProviderConfiguration<FileLoggerProvider> providerConfiguration)
: base(providerConfiguration.Configuration)
{
}
}
public class BlobLoggerOptions
{
public string? Path { get; set; }
public string? Interval { get; set; }
public string? AzureStorage { get; set; }
}
internal class BlobLoggerOptionsSetup : ConfigureFromConfigurationOptions<BlobLoggerOptions>
{
public BlobLoggerOptionsSetup(ILoggerProviderConfiguration<BlobLoggerOptions> providerConfiguration)
: base(providerConfiguration.Configuration)
{
}
}
And how I add them:
public static class LoggingBuilderExtensions
{
public static ILoggingBuilder AddFileLogger(this ILoggingBuilder builder)
{
builder.AddConfiguration();
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<ILoggerProvider,
FileLoggerProvider>());
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IConfigureOptions<FileLoggerOptions>,
FileLoggerOptionsSetup>());
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IOptionsChangeTokenSource<FileLoggerOptions>,
LoggerProviderOptionsChangeTokenSource<FileLoggerOptions, FileLoggerProvider>>());
return builder;
}
public static ILoggingBuilder AddAzureBlobLogger(this ILoggingBuilder builder)
{
builder.AddConfiguration();
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<ILoggerProvider,
BlobLoggerProvider>());
/* switch to this to get the "File" properties
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IConfigureOptions<FileLoggerOptions>,
FileLoggerOptionsSetup>());
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IOptionsChangeTokenSource<FileLoggerOptions>,
LoggerProviderOptionsChangeTokenSource<FileLoggerOptions, BlobLoggerProvider>>());
*/
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IConfigureOptions<BlobLoggerOptions>,
BlobLoggerOptionsSetup>());
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IOptionsChangeTokenSource<BlobLoggerOptions>,
LoggerProviderOptionsChangeTokenSource<BlobLoggerOptions, BlobLoggerProvider>>());
return builder;
}
}
Use
BlobLoggerProvider
in below method, notBlobLoggerOptions
. And please check the test result first.