Serilog - keep only 7 latest files - serilog

I use serilog and have the date as a part of my filename. This is an easy way to get to the file. Currently I am checking nightly events and I and just pick the last file in the morning.
Now, I only want to keep 7 days. This is was retainedFileCountLimit is for.
However that does not work as I want it too, as it might check for that specific filename.
How can I do this? (I had my own log system which deleted files older than a week)
Where are all serilog properties described? I am missing an overview of those.
//Add Serilog
string logFileName = HostingEnvironment.MapPath(#"~/new_" + DateTime.Now.ToString("yyyyMMdd") + ".log");
Log.Logger = new LoggerConfiguration()
.WriteTo.File(
path: logFileName,
retainedFileCountLimit: 7,
shared: true,
rollingInterval: RollingInterval.Day,
rollOnFileSizeLimit: true,
fileSizeLimitBytes: 123456,
flushToDiskInterval: TimeSpan.FromSeconds(5))
.CreateLogger();
Log.Information("Starting Serilog #1");

The File sink automatically includes the date in the file name - do not include DateTime.Now in the file name and let Serilog take care of that and you should get the retention that you expect.
var log = new LoggerConfiguration()
.WriteTo.File
(
"new_.txt", // <<<<<<<<<<<<<<<<<<<<<<
rollingInterval: RollingInterval.Day,
retainedFileCountLimit: 7,
// ...
)
.CreateLogger();
This will append the time period to the filename, creating a file set like:
new_20180631.txt
new_20180701.txt
new_20180702.txt
The documentation of the File sink is the repository on GitHub.

Related

Single log file

I would like to have a single log file that will be rolled on the size limit, previous file will be removed so there is only one log file at a time. Exaxmple:
logs.txt raches 10MB --> delete logs.txt start writing to logs_001.txt
My current code is:
Log.Logger = new LoggerConfiguration()
.WriteTo.File(
LogFile,
rollOnFileSizeLimit: true,
retainedFileCountLimit: 1,
fileSizeLimitBytes: 10485760) //10MB
.CreateLogger();
The code is from a Xamarin Forms project and it's executed every time the application is initialized.
The issue with that code is that on each application initialization a new log file is created, the previous one is deleted but the file size limit is not respected. So if the log file size is
lower than 10MB it will still roll to a new file at each start of the application.
The solution was to simply remove rollOnFileSizeLimit: true

Creating log backup file with .bak extension using serilog

I am using Serilog framework for logging in my application. The file size limit i have given is 2MB. So when the file reaches 2MB, new file is created with like app_001.log, existing app.log is a back up file.
But what i want to do is when the file reaches 2MB, it should rename app.log to app.log.bak and write the new logs to newly created app.log file.
_logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.File(_filepath, restrictedToMinimumLevel: LogEventLevel.Debug, shared: true, rollOnFileSizeLimit: true, fileSizeLimitBytes: 2000000)
.CreateLogger();
You can create a class that derives from FileLifecycleHooks and override OnFileOpened and add some logic to check for the existence of app_*.log files and rename them to app_*.bak.
https://github.com/serilog/serilog-sinks-file#extensibility

Serilog : how do you specify a filter expression in config file

I am trying to specify this filter in the appsettings .json file
.Filter.ByExcluding(Matching.FromSource("Microsoft.AspNetCore.Hosting.Internal.WebHost"))
The above syntax works when specified in c#
But trying to specify the same in a json file does not work.
"Filter": [
{
"Name": "ByExcluding",
"Args": {
"expression": "Matching.FromSource = 'Microsoft.AspNetCore.Hosting.Internal.WebHost'"
}
}
You need to use Serilog.Expressions for this:
Install-Package Serilog.Expressions
The filter section in appsettings.json looks like:
"Filter": [
{
"Name": "ByExcluding",
"Args": {
"expression": "SourceContext = 'Microsoft.AspNetCore.Hosting.Internal.WebHost'"
}
}
],
In this specific case, I'd suggest considering level overrides as an alternative that will turn off a specific namespace more efficiently.
The answer by Nicholas Blumhardt is correct, but there are some extra details that you might find useful.
If you do not have a piece of source code like the following (during serilog initialization)
.Filter.ByExcluding(Matching.FromSource("Microsoft.AspNetCore.Hosting.Internal.WebHost"))
in one of your .cs files, then the Serilog.Filters.Expressions.dll file will not be loaded, and your filter expression will just fail silently when the config file is loaded. So be sure to refer to .Filter in your .cs source (even if it never gets called)
Another item that is useful for debugging serilog itself (especially config file start ups like this example) is to add serilog debugging of itself to the console
// this is just to check on serilog startup and configuration, problems with serilog itself get written to console
Serilog.Debugging.SelfLog.Enable(msg => Console.WriteLine(msg));
Then run your .cs app in debug mode and check for messages on the console as you initialize serilog from its config file.
It is way easier to do using Filter.ByIncludingOnly your "MyWellKnownNamespace"
That's way easier than trying to figure out exactly what namespace the unwanted messages are coming from:
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(_configuration)
.Filter.ByIncludingOnly( Matching.FromSource("MyWellKnownNamespace") )
.CreateLogger();

Log4J2 - changing the fileName at runtime

Can anybody let me know if it is possible to change the fileName at runtime.
I have migrated my log4j.properties to log4j2.properties successfully so far. The appenders, loggers are all being created. If I hard code the fileName then my logs are getting populated. But unfortunately the logname has to be the service name and I will know the service name only at runtime.This was possible earlier with Log4j 1.x. Earlier Call to fileAppender.setFile(logFile.getAbsolutePath()); would change the fileName during runtime. I now need to do something similar with log4J 2.4.1. I tried removing the appender,recreating it programmatically and adding the appender to the configuration but no success. Empty logfiles are being created but with the correct name. Please can anybody help me as I am just not able to figure this out. Below is my code snippet where I am trying to delete,recreate the appender.
RollingFileAppender fileAppender = (RollingFileAppender) this.config.getAppender(loggerName);
String filePattern = fileAppender.getFilePattern();
TriggeringPolicy policy = fileAppender.getTriggeringPolicy();
RolloverStrategy strategy = fileAppender.getManager().getRolloverStrategy();
PatternLayout layout = (PatternLayout) fileAppender.getLayout();
Filter filter = fileAppender.getFilter();
LoggerConfig lgConfig = this.config.getLogger(loggerName);
RollingFileAppender rollingFile = RollingFileAppender.createAppender(fileName, filePattern, "true", loggerName, (String)null, (String)null, (String)null, policy, strategy, layout, filter, (String)null, "false", (String)null, config);
config.removeAppender(loggerName);
config.removeLogger(loggerName);
config.addLogger(loggerName, lgConfig);
context.updateLoggers();
config.addAppender((Appender)rollingFile);
logger = LogManager.getLogger(loggerName);
"fileName" is already set by the time we reach this bit of code.
You should be able to create a custom Lookup to get your service name and then reference that in the configuration file.
Here is an example of how to create a custom Lookup.

Is it possible to configure a Serilog Sub-logger from appSettings

This is what I am doing now:
Log.Logger = new LoggerConfiguration()
.ReadFrom.AppSettings()
.WriteTo.Logger(l => l.Filter.ByIncludingOnly(Matching.WithProperty("XXX")).WriteTo.File("output.txt"))
.CreateLogger();
I have my main Logger set up in app.config, but I can't figure out the syntax for specifying a sub-logger there. I'd really like to avoid mixing code and appSettings configuration.
No, this isn't possible using Serilog as it is today.

Resources