0

I am trying to set up a logging system that adds log files to subfolders based on the year. However I've been unable to programmatically specify the year. I can hardcode it and it works fine, but I would like to be able to specify it programmatically. When I do this, ASP.Net takes it as a literal value and either creates a folder based on that literal string, or it doesn't do anything because the string contains characters that can't exist (or can't start) a folder name, such as the example I'm showing below. Is there a way to do this or am I stuck with hardcoding?

"Serilog": 
{
    "MinimumLevel": 
    {
        "Default": "Debug",
        "Override": 
        {
            "Microsoft": "Information",
            "System": "Information"
        }
    },
    "WriteTo": 
    [
        {
            "Name": "Console",
            "Args": 
            {
            "outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"
            }
        },
        {
            "Name": "Logger","Args": 
            {
                "configureLogger": 
                    {
                        "WriteTo": 
                        [
                            {
                                "Name": "File",
                                "Args": 
                                {
                                    "path": "C:/data/Logs/ErrorLogs/{Date:yyyy}/errorlog_.log",
                                    "rollingInterval": "Day",
                                    "retainedFileCountLimit": null,
                                    "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}"
                                }
                            }
                        ],
                        "Filter": 
                        [
                            {
                                "Name": "ByIncludingOnly",
                                "Args": 
                                {
                                    "expression": "(@Level = 'Error' or @Level = 'Fatal')"
                                }
                            }
                        ]
                    }
                }
            },

...

3
  • Which logger are you using? Serilog? Log4Net? Or something else? (This avoids needing to guess.) Commented Aug 12, 2024 at 17:54
  • @Richard - as the code shows above as well as my tag, Serilog. Commented Aug 12, 2024 at 18:02
  • You can can certainly do this in code (see readme). But nothing looks like the implementation treats the path from configuration as anything more than a plain string. Commented Aug 12, 2024 at 21:19

1 Answer 1

0

After a bunch more research and testing I found a solution to this - instead of using appsettings.json, you can make similar configurations to Serilog sink files in your program.cs, so here is the one that I ended up that worked for me:

var currentYear = DateTime.Now.Year.ToString(); // Get the current year

Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(builder.Configuration) // Read other settings from appsettings.json
.Enrich.FromLogContext()
.WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}")
.WriteTo.File($"C:/data/Logs/ErrorLogs/{currentYear}/errorlog_.log",

    rollingInterval: RollingInterval.Day,
    retainedFileCountLimit: null,
    outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}",

    restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Error)
// Filter for Error and Fatal
.WriteTo.File($"C:/data/Logs/ActivityLogs/{currentYear}/activitylog_.log",
    rollingInterval: RollingInterval.Day,
    retainedFileCountLimit: null,
    outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}")
    .Filter.ByExcluding(Matching.WithProperty<Serilog.Events.LogEventLevel>("Level",
                         level => level != Serilog.Events.LogEventLevel.Information)) // Filter for Information only
    .Filter.ByExcluding(le =>
        le.MessageTemplate.Text.Contains("The file ") || // More specific for "The File"
        le.RenderMessage().StartsWith("Request") || // Use RenderMessage for "Request" 
        le.MessageTemplate.Text.StartsWith("Executing") ||
        le.MessageTemplate.Text.StartsWith("Route") ||
        le.MessageTemplate.Text.StartsWith("Accessing") ||
        le.MessageTemplate.Text.StartsWith("Executed"))
.CreateLogger();
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.