Can't take the result of "${configsetting:item=${gdc:item=serviceName}.LogLevel}"
Hi, I created appsettings where I have file target that uses ${gdc:item=serviceName} and writes logs from different services in different files
"type": "File",
"fileName": "${gdc:assemblyFolder}/logs/${gdc:item=serviceName}/${date:format=yyyy-MM-dd}/${gdc:item=serviceLogName}-${date:format=yyyy-MM-dd}.log",
"layout": "${longdate:universalTime=true}|${level:uppercase=true}|${logger}|${scopeproperty:correlationId}|${message:exceptionSeparator=\r\n:withException=true}"
}
{
"logger": "Service1.*",
"minLevel": "${configsetting:item=Service1.LogLevel}",
"ruleName": "Service1",
"writeTo": "fileTarget, consoleTarget"
}
It gets lodlevels from this file
"Service1": {
"LogLevel": "Debug",
"CheckIntervalInMinutes": 1,
...
but my services also uses some packages like TS.Common, so I need to write there logs too. But I can't understand how to use the same log level that service. I tried smth like that:
{
"logger": "TS.*",
"ruleName": "ExecutePackages",
"minLevel": "${configsetting:item=${gdc:item=serviceName}.LogLevel}",
"writeTo": "fileTarget, consoleTarget"
}
but with no effect. Maybe someone knows how to use GDC and configsetting together?
Thanks :)
Related
I have some rules, that logging their projects
{
"logger": "Alpha.*",
"minLevel": "${configsetting:item=Alpha.LogLevel}",
"ruleName": "Alpha",
"writeTo": "fileTarget, consoleTarget"
},
{
"logger": "Beta.*",
"minLevel": "${configsetting:item=Beta.LogLevel}",
"ruleName": "Beta",
"writeTo": "fileTarget, consoleTarget"
},
Now I add few packages to my solution (like AB.Common.Exception), and I want to add their logs for the log of project.
For example, if package was used by Alpha, log from AB might be added to "ruleName": "Alpha", but not to "Beta".
Is there any way to do this?
Regards.
Updated
Ok, I found possible answer with rule in end
{
"logger": "Alpha.*",
"minLevel": "${configsetting:item=Alpha.LogLevel}",
"ruleName": "Alpha",
"writeTo": "fileTarget, consoleTarget"
},
{
"logger": "Beta.*",
"minLevel": "${configsetting:item=Beta.LogLevel}",
"ruleName": "Beta",
"writeTo": "fileTarget, consoleTarget"
},
{
"logger": "*",
"minLevel": "Trace",
"ruleName": "AB",
"writeTo": "fileTarget, consoleTarget"
}
But I want to set logLevel from ${configsetting:item=Alpha.LogLevel} or ${configsetting:item=Beta.LogLevel}
Ok, my answer now looks like that
{
"logger": "Alpha.*",
"minLevel": "${configsetting:item=Alpha.LogLevel}",
"ruleName": "Alpha",
"writeTo": "fileTarget, consoleTarget"
},
{
"logger": "Beta.*",
"minLevel": "${configsetting:item=Beta.LogLevel}",
"ruleName": "Beta",
"writeTo": "fileTarget, consoleTarget"
},
{
"logger": "*",
"minLevel": "${configsetting:item=Alpha.LogLevel}",
"ruleName": "ABtoAlpha",
"writeTo": "fileTarget, consoleTarget"
},
{
"logger": "*",
"minLevel": "${configsetting:item=Beta.LogLevel}",
"ruleName": "ABtoBeta",
"writeTo": "fileTarget, consoleTarget"
}
I think it's not so beautiful I hoped, but it works 😅
Upd: OK, it don't work like I want - it writes all another logs only with minLevel ${configsetting:item=Alpha.LogLevel}
Maybe you just need to add "finalMinLevel": "Off" (Introduced with NLog v5), so it doesn't reach the last catch-all-rule:
"rules": [
{
"logger": "Alpha.*",
"minLevel": "${configsetting:item=Alpha.LogLevel}",
"ruleName": "Alpha",
"writeTo": "fileTarget, consoleTarget",
"finalMinLevel": "Off"
},
{
"logger": "Beta.*",
"minLevel": "${configsetting:item=Beta.LogLevel}",
"ruleName": "Beta",
"writeTo": "fileTarget, consoleTarget",
"finalMinLevel": "Off"
},
{
"logger": "*",
"minLevel": "Trace",
"ruleName": "AB",
"writeTo": "fileTarget, consoleTarget"
}
]
If output always should be sent to the same targets, then it can be simplied with just using "finalMinLevel": "${configsetting:item=LogLevel}"
"rules": [
{
"logger": "Alpha.*",
"finalMinLevel": "${configsetting:item=Alpha.LogLevel:whenEmpty=Debug}"
},
{
"logger": "Beta.*",
"finalMinLevel": "${configsetting:item=Beta.LogLevel:whenEmpty=Debug}"
},
{
"logger": "*",
"minLevel": "Trace",
"writeTo": "fileTarget, consoleTarget"
}
]
See also: https://github.com/NLog/NLog/wiki/Configuration-file#rules
I'm trying to log to a file using NLog based on a globally-set log level. I'm unsure if this is possible from everything I can dig up.
Essentially, I want to have a global setting in my appconfig.json that has the log level. Default would be Debug, but Trace would be another option. If I select Debug, I want to log everything from Debug up to Fatal in a file called log-debug.txt. This seems pretty reasonable; it's the base tutorial case from what I can tell, and I've made that work.
Here's the other thing, though: if I set the global log level to Trace, I want everything from Trace on up to log to log-trace.txt. My initial thought was to add a new config rule, so I added the second one in the rules collection, but from everything I've read that would end up with the debug messages in one file and the trace messages in another.
The purpose of this is extreme-case debugging (i.e., user doesn't have any idea how they got to that state, so flip the setting from "Debug" to "Trace", play with it again, and when you hit the bug send me the log-trace.txt), so splitting the debug and trace messages into different files would defeat the purpose.
How would I go about doing this?
This is a WPF app, so I'm setting the global level by using this in app.xaml.cs:
serviceCollection.AddLogging(builder =>
{
builder.ClearProviders();
// Haven't written the code to pull it from the config file yet, but this is how
// I would set it.
builder.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
builder.AddNLog();
});
appconfig.json
{
"settings": {
"logLevel": "Debug"
},
"NLog": {
"internalLogLevel": "Info",
"autoReload": true,
"targets": {
"logfile-debug": {
"type": "File",
"fileName": "log-debug.txt",
"layout": "${longdate}|${level}|${message}|${exception:format=tostring}"
},
"logfile-trace": {
"type": "File",
"fileName": "log-trace.txt",
"layout": "${longdate}|${level}|${message}|${exception:format=tostring}",
},
"logconsole": {
"type": "Debugger",
"layout": "${longdate}|${level}|${message}|${exception:format=tostring}"
}
},
"rules": [
{
"logger": "*",
"minLevel": "Debug",
"writeTo": "logfile-debug,logconsole"
},
{
"logger": "*",
"minLevel": "Trace",
"writeTo": "logfile-trace,logconsole"
}
]
}
}
You can do this:
void EnableGlobalTrace(bool enable)
{
NLog.GlobalDiagnosticsContext.Set("GlobalTraceLevel", enable ? "Trace" : "Off");
NLog.LogManager.ReconfigureExistingLoggers();
}
And have the rules like this:
"rules": [
{
"logger": "*",
"minLevel": "Debug",
"writeTo": "logfile-debug,logconsole"
},
{
"logger": "*",
"minLevel": "${gdc:GlobalTraceLevel:whenEmpty=Off}",
"writeTo": "logfile-trace"
}
]
See also: https://github.com/NLog/NLog/wiki/Filtering-log-messages#semi-dynamic-routing-rules
See also: https://github.com/NLog/NLog/wiki/Environment-specific-NLog-Logging-Configuration
I'm using ASP net core 6 and I don't have the startup class. Of course, I programmed the whole thing in Visual studio code 2022
The problem:
enter image description here
I don't want the location to be shown in the console.
You can see Below AppSettings.Json
"AllowedHosts": "*",
"Serilog": {
"Using": [],
"MinimunLevel": {
"Default": "Information",
"Overrite": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId", "WithThreadId" ],
"WriteTo": [
{ "Name": "Console" },
{
"Name": "File",
"Args": {
"path": "C:\\Demos\\Logs\\Log.txt"
}
Otherwise, all the other information I need is shown and it works, only I don't want the location to be shown
Is there a way to differentiate what level is logged between the different loggers for Serilog? I want to be able to log MinimumLevel Debug to the console output but only Warning and above to my file output. I am using ASP.NET Core 2.1 and this is what the appsetting.json currently looks like:
"Serilog": {
"Using": [ "Serilog.Sinks.Console" ],
"MinimumLevel": "Debug",
"WriteTo": [
{
"Name": "RollingFile",
"IsJson": true,
"Args": {
"pathFormat": "C:\\Logs\\Log-{Hour}.json",
"formatter": "Serilog.Formatting.Json.JsonFormatter, Serilog"
}
},
{
"Name": "Console"
}
]
},
Is it something like another parameter under "Args"? I've tried "minimumnLevel" in this location but it did not work.
The setting you're looking for is restrictedToMinimumLevel. This GitHub issue shows some examples of this, but for your example, you just need to add restrictedToMinimumLevel to your Args for RollingFile:
"Serilog": {
"Using": [ "Serilog.Sinks.Console" ],
"MinimumLevel": "Debug",
"WriteTo": [
{
"Name": "RollingFile",
"IsJson": true,
"Args": {
"pathFormat": "C:\\Logs\\Log-{Hour}.json",
"formatter": "Serilog.Formatting.Json.JsonFormatter, Serilog",
"restrictedToMinimumLevel": "Warning"
}
},
{
"Name": "Console"
}
]
},
Working from the answers above, this is how I set it up in code as opposed to config
LoggerConfiguration GetConfig()
=> new LoggerConfiguration()
.WriteTo.Seq(serverUrl: "http://localhost:5341", restrictedToMinimumLevel: LogEventLevel.Debug)
.WriteTo.Console(restrictedToMinimumLevel: LogEventLevel.Error);
var logger = GetConfig().CreateLogger();
builder.RegisterInstance(logger).As<ILogger>();
After I did this, it worked for log level Information and above. Debug didn't work. This post explained why.
I had to set a 'global' minimum level like this.
LoggerConfiguration GetConfig()
=> new LoggerConfiguration()
.WriteTo.Seq(serverUrl: "http://localhost:5341", restrictedToMinimumLevel: LogEventLevel.Debug)
.WriteTo.Console(restrictedToMinimumLevel: LogEventLevel.Error)
.MinimumLevel.Verbose();
In your configuration you have one Serilog logger, but you have 2 sinks. One of your sinks is RollingFile and the other is Console.
You can override (but only raise) the minimum logging level per sink, The argument is called restrictedToMinimumLevel.
Since you want to raise the minimum logging level from your logger's default Debug to Warning in your file sink, in your appsettings.json file, it would look like this:
"Serilog": {
"Using": [ "Serilog.Sinks.Console" ],
"MinimumLevel": "Debug",
"WriteTo": [
{
"Name": "RollingFile",
"IsJson": true,
"Args": {
"pathFormat": "C:\\Logs\\Log-{Hour}.json",
"formatter": "Serilog.Formatting.Json.JsonFormatter, Serilog",
"restrictedToMinimumLevel": "Warning"
}
},
{
"Name": "Console"
}
]
},
I have a .NET Core 2.0 application in which I successfully use Serilog for logging. Now, I would like to log some database performance statistics to a separate sink (they are not for debugging, which basically is the purpose of all other logging in the application, so I would like to keep them separate) and figured this could be accomplished by creating the DB statistics logger with Log.ForContext<MyClass>().
I do not know how I am supposed to configure Serilog using my appsettings.json to log my "debug logs" to one sink and my DB statistics log to another? I am hoping it is possible to do something like:
"Serilog": {
"WriteTo": [
{
"Name": "RollingFile",
"pathFormat": "logs/Log-{Date}.log",
"Filter": {
"ByExcluding": "FromSource(MyClass)"
}
},
{
"Name": "RollingFile",
"pathFormat": "logs/DBStat-{Date}.log",
"Filter": {
"ByIncludingOnly": "FromSource(MyClass)"
}
}
]
}
The "Filter" parts of the configuration is pure guesswork on my part. Is this possible using my configuration filer or do I need to do this in code in my Startup.cs file?
EDIT: I have got it working using the C# API but would still like to figure it out using JSON config:
Log.Logger = new LoggerConfiguration()
.WriteTo.Logger(lc => lc
.Filter.ByExcluding(Matching.FromSource<MyClass>())
.WriteTo.LiterateConsole())
.WriteTo.Logger(lc => lc
.Filter.ByExcluding(Matching.FromSource<MyClass>())
.WriteTo.RollingFile("logs/DebugLog-{Date}.log"))
.WriteTo.Logger(lc => lc
.Filter.ByIncludingOnly(Matching.FromSource<MyClass>())
.WriteTo.RollingFile("logs/DBStats-{Date}.log", outputTemplate: "{Message}{NewLine}"))
.CreateLogger();
I completed this work today, and thought that I'd provide a proper answer since it took me quite a few posts, issues and other pages to work through to get this sorted out.
It's useful to have all the logs, but I also wanted to log only my API code separately, and omit the Microsoft. namespace logs. The JSON config to do that looks like this:
"Serilog": {
"Using": [ "Serilog.Sinks.File" ],
"MinimumLevel": "Debug",
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "/var/logs/system.log",
... //other unrelated file config
}
},
{
"Name": "Logger",
"Args": {
"configureLogger": {
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "/var/logs/api.log",
... //other unrelated file config
}
}
],
"Filter": [
{
"Name": "ByExcluding",
"Args": {
"expression": "StartsWith(SourceContext, 'Microsoft.')"
}
}
]
}
}
}
],
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ]
... //Destructure and other config
}
The top-level WriteTo is the first simple, global, sink. All log events write to this. If you add a Filter section on the same level as this, it will affect all configured WriteTo elements.
Then I configure another WriteTo as a Logger (not File), but the Args for this looks different and has a configureLogger element which serves the same purpose as Serilog on the top level, that is to say, it is the top level of the sub-logger. This means that you can easily split out the config for this into a separate file and add it additionally in the config builder (see bottom).
From here, this sub-logger works the same way: You can configure multiple WriteTos, and the Filter element on this level will affect only this sub-logger.
Simply add more "Name": "Logger" elements to the top level WriteTo section and setup filters for each one separately.
Note
It is also important to note that, even though you are doing all this in config and not referencing a single bit of the Serilog.Filters.Expressions package in your code, you still have to add the NuGet reference to that package. It doesn't work without the package reference.
About splitting the config:
If I have to add more loggers, I would definitely split out the different loggers into separate files for clarity, e.g.
appsettings.json:
"Serilog": {
"Using": [ "Serilog.Sinks.File" ],
"MinimumLevel": "Error",
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "/var/logs/system.log",
...
}
},
{
"Name": "Logger",
"Args": {
"configureLogger": {} // leave this empty
}
}
],
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
...
apilogger.json:
{
"Serilog:WriteTo:1:Args:configureLogger": { //notice this key
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "/var/logs/api_separateFile.log",
...
}
}
],
"Filter": [
{
"Name": "ByExcluding",
"Args": {
"expression": "StartsWith(SourceContext, 'Microsoft.')"
}
}
]
}
}
And then adjust my IWebHost builder to include the additional config:
WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddJsonFile("apilogger.json", optional: false, reloadOnChange: false);
})
.UseStartup<Startup>();
This way it is easier to understand, read and maintain.
I had to do a similar thing, but in code, not JSON. Using a logger as a sink, as described at the bottom of https://github.com/serilog/serilog/wiki/Configuration-Basics did the trick.
In my case I wanted to log everything to a file and to the console, except that messages from a specific source should go only to the file:
private static bool SourceContextEquals(LogEvent logEvent, Type sourceContext)
=> logEvent.Properties.GetValueOrDefault("SourceContext") is ScalarValue sv && sv.Value?.ToString() == sourceContext.FullName;
private static ILogger CreateLogger() =>
new LoggerConfiguration()
.WriteTo.File("mylog.log")
.WriteTo.Logger(lc =>
lc.Filter.ByExcluding(le => SourceContextEquals(le, typeof(TypeThatShouldLogOnlyToFile)))
.WriteTo.Console()
)
.CreateLogger();
Writing only entityframework log to a file is done below but we need to install Serilog.Filters.Expressions nuget package
"Serilog": {
"MinimumLevel": {
"Default": "Debug",
"Override": {
"Microsoft": "Warning",
"System": "Warning",
"Microsoft.EntityFrameworkCore": "Information"
}
},
"WriteTo": [
{
"Name": "Logger",
"Args": {
"configureLogger": {
"Filter": [
{
"Name": "ByIncludingOnly",
"Args": {
"expression": "StartsWith(SourceContext, 'Microsoft.EntityFrameworkCore')"
}
}
],
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "C:\\LOGS\\TestService_EF_.json",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}",
"rollingInterval": "Day",
"retainedFileCountLimit": 7
}
}
]
}
}
}
]
}