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.
Related
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.
I am trying to build my own micro services architecture and am stuck at the API.Gateway part.
I am trying to make Ocelot V14 find all configuration ocelot.json or configuration.json files inside the .sln file.
In the Program.cs file I am trying to merge configuration files with the following code from this link https://ocelot.readthedocs.io/en/latest/features/configuration.html#react-to-configuration-changes
builder.ConfigureServices(s => s.AddSingleton(builder))
.ConfigureAppConfiguration((hostingContext, config) =>
{
config
.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
.AddJsonFile("appsettings.json", true, true)
.AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true)
.AddOcelot(hostingContext.HostingEnvironment)
.AddEnvironmentVariables();
})
.UseStartup<Startup>();
When I run this the application creates the following ocelot.json file inside my OcelotApiGw Project
{
"ReRoutes": [
]
}
The problem is that it is empty and the reroutes do not work. When I paste the desired reroutes into this ocelot.json file the reroutes work, that is not the desired functionality I want.
What I want is to merge the configuration file automatically from different .json files.
Any help would be greatly appreciated.
How eShopOnContainers implements it this way with Ocelot V12
IWebHostBuilder builder = WebHost.CreateDefaultBuilder(args);
builder.ConfigureServices(s => s.AddSingleton(builder))
.ConfigureAppConfiguration(ic => ic.AddJsonFile(Path.Combine("configuration", "configuration.json")))
.UseStartup<Startup>();
In case you need more code, file structures or anything else just comment and ask.
Not sure if this is what you are looking for? This is the way Ocelot merges multiple routing files together
https://ocelot.readthedocs.io/en/latest/features/configuration.html#merging-configuration-files
We don't use this but this is how we have our startup defined:
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddJsonFile(this.env.IsDevelopment() ? "ocelot.json" : "ocelot.octopus.json")
.AddEnvironmentVariables();
So we have our standard appSettings plus the Ocelot one we use that Octopus will transform various variables we want when our Ocelot instance is deployed out into our test/production envs (or just our test/local one).
This seems to be the bit that defines what to do for multiple files:
In this scenario Ocelot will look for any files that match the pattern
(?i)ocelot.([a-zA-Z0-9]*).json and then merge these together. If you
want to set the GlobalConfiguration property you must have a file
called ocelot.global.json.
Not sure if you need to explicitly define each file (unless they can be defined via a variable like {env.EnvironmentName}) but that should be easy enough to test.
Sorry if I have got the wrong end of the stick but hope this helps.
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();
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.
Consider this app.config appSetting entry:
<add key="serilog:write-to:RollingFile.pathFormat"
value="ServerServiceApp-{Date}.log" />
This is done at app startup:
Log.Logger = new LoggerConfiguration()
.ReadFrom.AppSettings()
.Enrich.WithThreadId()
.CreateLogger();
This is in a Windows service app. The log file ends up here:
C:\Windows\SysWOW64
Clearly, we’d rather have the log file end up in the same directory that houses this service’s .exe (customers don’t want us writing stuff to SysWOW64). But how?
We need the ReadFrom.AppSettings in there so that the customer can supply serilog settings in the app.config, as necessary.
Is there some way to change the directory used for the log file after the ReadFrom.AppSettings has been done?
Would be awesome if we could say something like:
<add key="serilog:write-to:RollingFile.pathFormat"
value="{ApDomainBaseDirectory}\ServerServiceApp-{Date}.log" />
(And where is {Date}, which can be put in the file path, documented?)
Just put this before the creation of LoggerConfiguration:
Environment.CurrentDirectory = AppDomain.CurrentDomain.BaseDirectory;
Then File.path will be constructed based on the project root path.
The best place for services to write their logs is %PROGRAMDATA% which, by default, is in C:\ProgramData\.
Try:
<add key="serilog:write-to:RollingFile.pathFormat"
value="%PROGRAMDATA%\ServerService\Logs\log-{Date}.txt" />
(Program Files is usually considered to be read-only, and writing stuff here will lead to oddities being left behind unexpectedly during uninstall.)