Hello @David Thielen ,
I made some modifications to your code and it works fine with me, please let me know if I understand wrong.
Here is my sample code.
appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Warning",
"LouisHowe": "Information",
"ThirdPartyServices": "Information",
"CommonUtilities": "Information",
"Microsoft": "Warning"
},
"File": {
"Path": "C:/temp/log-{0:yyyy-MM-dd}.txt",
"Interval": "Day",
"LogLevel": {
"Default": "Information",
"LouisHowe": "Trace",
"Microsoft": "Warning"
}
}
},
"AllowedHosts": "*"
}
FileLoggerExtensions.cs
namespace ilogger_sink
{
// Extension method to add custom file logger
public static class FileLoggerExtensions
{
public static ILoggingBuilder AddFileLogger(this ILoggingBuilder builder, IConfiguration configuration)
{
builder.Services.AddSingleton<ILoggerProvider, FileLoggerProvider>();
builder.Services.Configure<FileLoggerOptions>(configuration.GetSection("Logging:File"));
return builder;
}
}
}
FileLoggerProvider.cs
using Microsoft.Extensions.Options;
namespace ilogger_sink
{
public class FileLoggerProvider : ILoggerProvider
{
private readonly FileLoggerOptions? _options;
public FileLoggerProvider(IOptions<FileLoggerOptions> options)
{
_options = options.Value;
}
public ILogger CreateLogger(string categoryName)
{
return new FileLogger(_options.Path);
}
public void Dispose() { }
}
}
FileLoggerOptions.cs
namespace ilogger_sink
{
// File logger options
public class FileLoggerOptions
{
public string? Path { get; set; }
}
}
FileLogger.cs
namespace ilogger_sink
{
public class FileLogger : ILogger
{
private readonly string? _logDirectory;
private readonly string? _logFileFormat;
public FileLogger(string logPathFormat)
{
_logDirectory = Path.GetDirectoryName(logPathFormat);
_logFileFormat = Path.GetFileName(logPathFormat);
}
public IDisposable? BeginScope<TState>(TState state) => null;
public bool IsEnabled(LogLevel logLevel) => true;
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
if (!IsEnabled(logLevel))
return;
string message = formatter(state, exception);
// Using string format to insert the current date into the filename
string filename = String.Format(_logFileFormat, DateTime.UtcNow);
string logFilePath = Path.Combine(_logDirectory, filename);
try
{
System.IO.File.AppendAllText(logFilePath, message + Environment.NewLine);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"Failed to log message: {ex}");
}
}
}
}
Program.cs
...
namespace ilogger_sink
{
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.Logging.ClearProviders();
builder.Logging.AddConsole();
builder.Logging.AddFileLogger(builder.Configuration);
// Add services to the container.
builder.Services.AddRazorPages();
...
var app = builder.Build();
...
app.Run();
}
}
}
If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.
Best regards,
Jason