serilog-settings-configuration icon indicating copy to clipboard operation
serilog-settings-configuration copied to clipboard

How to create the log file by process name?

Open xuliujian opened this issue 1 year ago • 3 comments

I create a common trace library for other solutions. But I can not find a way to configure the path dynamicly. I tried to create a enrich to add a property named InstanceName, but it does not work.

{ "Serilog": { "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ], "MinimumLevel": "Debug", "WriteTo": [ { "Name": "Console", "Args": { "outputTemplate": "{TraceCategory} - {Timestamp:o} [{Level:u3}] {Message}{NewLine}" } }, { "Name": "File", "Args": { "path": "./logs/{InstanceName}.log", "outputTemplate": "{TraceCategory} - {Timestamp:o} [{Level:u3}] {Message}{NewLine}", "rollingInterval": "Day", "retainedFileCountLimit": 7 } } ], "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId", "WithTraceCategory", "WithInstanceName" ], "Destructure": [ { "Name": "ToMaximumDepth", "Args": { "maximumDestructuringDepth": 4 } }, { "Name": "ToMaximumStringLength", "Args": { "maximumStringLength": 100 } }, { "Name": "ToMaximumCollectionCount", "Args": { "maximumCollectionCount": 10 } } ] } }

xuliujian avatar Jan 31 '24 08:01 xuliujian

You're best off asking stuff like this on stackoverflow - anyone that watches this repo watches the serilog tag there - and be sure to take the time to format your question and include any information about messages you receive (search up about Serilog Selflog)

bartelink avatar Jan 31 '24 09:01 bartelink

Enrichers don't work for filenames, only for log message templates.

I don't believe there is a way to name the log file based on the process name while using JSON config. Instead, I think you'll need to configure the loggewr in code instead. You probably already know this if you've tried writing an enricher, but you can get the process name (without the file extension) by using:

System.Diagnostics.Process.GetCurrentProcess().ProcessName

cocowalla avatar Jan 31 '24 10:01 cocowalla

@cocowalla Thank you. At the moment, I have a workaround to implement this. I add a PlaceHolder flag such as ${InstanceName} in the path, and then read the appsettings.json and replace the PlaceHolder with the process name, then LogConfiguration reads from the configuration. But I think it is not too nice.

public static IConfigurationRoot ApplyPlaceHolder(this IConfigurationRoot configuration, string placeHolder, string placeTarget)
{
    var writeToDirectiveSection = configuration.GetSection("Serilog:WriteTo");

    if (writeToDirectiveSection.GetChildren().Any())
    {
        foreach (var sink in writeToDirectiveSection.GetChildren())
        {
            var pathConfigSection = sink.GetSection("Args:path");

            if (pathConfigSection != null && !string.IsNullOrEmpty(pathConfigSection.Value))
            {
                if (pathConfigSection.Value.Contains(placeHolder))
                {
                    pathConfigSection.Value = pathConfigSection.Value.Replace(placeHolder, placeTarget);
                }
            }
        }
    }

    return configuration;
}
            builder = new ConfigurationBuilder();
            configurationRoot = builder.AddJsonFile(Path.Combine(Directory.GetCurrentDirectory(), "appsettings.json")).Build();

            processName = Process.GetCurrentProcess().ProcessName;

            //Replace InstanceName with processName
            configurationRoot.ApplyPlaceHolder("${InstanceName}", processName);

            _loggerConfiguration = new LoggerConfiguration();
            _loggerConfiguration.ReadFrom.Configuration(configurationRoot)

xuliujian avatar Feb 01 '24 04:02 xuliujian