I had always imagined that
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
},
would set my project code's log level to Debug, and make Microsoft.* namespaces log at Information level or higher. It seems not. With this config, AspNetCore infrastructure logs at Debug level.
How do I target Microsoft.* to not use the Default level?
I'm using Serilog, but the injected Loggers are all Microsoft.Extensions.Logging.ILogger so I expected Microsoft.Extensions.Logging config to kick in.
Is this a mistaken assumption?
Yes, the assumption that Serilog will respect the Logging.LogLevel section when used with Extensions.Logging is wrong. It doesn't.
To read serilog levels from config, some options are:
use https://github.com/serilog/serilog-settings-configuration and use the config structure they give, especially the section at MinimumLevel, LevelSwitches, overrides
For those who do Serilog config in code, use something like this:
var defaultLogLevel = configuration.GetLogLevel("Default");
var aspNetCoreLogLevel = configuration.GetLogLevel("Microsoft.AspNetCore");
var microsoftLogLevel = configuration.GetLogLevel("Microsoft");
var logger = new LoggerConfiguration()
.MinimumLevel.Is(defaultLogLevel)
.MinimumLevel.Override("Microsoft.AspNetCore", aspNetCoreLogLevel)
.MinimumLevel.Override("Microsoft", microsoftLogLevel)
// ... etc ...
// ...
static LogEventLevel GetLogLevel(this IConfiguration configuration, string #namespace, string fallbackLevel = "Information")
{
return Enum.Parse<LogEventLevel>(configuration["Logging:LogLevel:" + #namespace] ?? fallbackLevel);
}
but the in-config approach for minimum levels has the advantage that you can make use of reloadOnChange
Related
Inside the Program.cs file of a .NET Core 3.1 Web API i got the following:
public class Program
{
private static string _someValue;
public Program(IConfiguration configuration)
{
_someValue = configuration["SOME_VALUE"]
}
inside the appsettings.json i got:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"SOME_VALUE": "value"
}
The problem is, i am not able to get the value "SOME_VALUE" from the appsettings.json. But i got this same value inside an Azure Key Vault and for some reason it gets the values from there. Can someone explain why that is the case?
Configuration providers are executed in a specific order
In your case, the Azure KeyVault will be at the top (or, to be more precise it is between AddUserSecrets and AddEnvironmentVariables)
See docs
Order configuration providers in code to suit the priorities for the underlying configuration sources that the app requires or use different variable name
I try to use default .NET core logging tools without any third party libs. So, question.
Does console logger with Json formatter support json serialization of objects?
I have the following config in appsettings
"Logging": {
"Console": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information",
"Microsoft.Hosting.Lifetime": "Information"
},
"FormatterName": "json",
"FormatterOptions": {
"SingleLine": true,
"JsonWriterOptions": {
"Indented": true
}
}
}
},
The following line
logger.LogDebug("RequestId:{requestId} ResponseInfo: {#response} ", requestName, response);
produces the output with string representation of #response object, internally it still invokes ToString(), but docs in Caution section says that
The logging infrastructure itself already manages the serialization of log messages, so if you're to pass in a log message that is already serialized—it will be double serialized
docs
And this point me that it should serialize object.
I think the build-in ILogger don't support this. That's why we can try the new System.Text.Json source generator.
The new System.Text.Json source generator can improve logging performance.
I think we also can choose third-party package, like Serilog. That should be more easy to do this.
I am using .NET Core 3.0 ASP.net and my appsettings.json looks like this
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*",
"Test":false
}
Is there any way that I could configure a certain publish profile (pubxml) to change the value of Test to either true or false ?
Yes, it's very easy. Currently, you are most likely using the Debug solution configuration for local development. Let's assume you also have Release as solution configuration and want to change certain settings upon publishing to Azure / with your publish profile.
Assuming you are using .NET Core 3.1 (also works with 2.x but the syntax is different), you can this code:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
webBuilder.UseEnvironment(Environment);
});
public static string Environment
{
get
{
string environmentName;
#if DEBUG
environmentName = "development";
#elif RELEASE
environmentName = "production";
#endif
return environmentName;
}
}
Also create a appsettings.product.json where you override specific values.
When you use your publish profile, simply select Release as solution configuration in the publish dialog. That way, you application will load appsettings.json for default values which will be overwritten by values in appsettings.production.json.
You can read more details in the docs.
In my repository class, I have my Config object and looks like my connection string is under:
Config > Providers > Microsoft.Configuration.Json.JsonConfigurationProvider > Data > ConnectionStrings.myConnectionString
This is what my appsettings.json looks like:
{
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Warning"
}
},
"ConnectionStrings": {
"myConnectionString": details..."
}
}
I'm trying to read myConnectionString as follows which is not working:
var cs = _config.GetSection("ConnectionStrings.myConnectionString").value;
What am I doing wrong?
UPDATE:
For some reason, I'm not seeing GetValue() method. I'm using ASP.NET Core 2.0.
Configuration API provides extension method for IConfiguration to simplify reading ConnectionStrings section:
// using Microsoft.Extensions.Configuration;
string connectionString = _config.GetConnectionString("myConnectionString");
what it does is return configuration?.GetSection("ConnectionStrings")?[name];
The issue seems to lie in the string path you are passing to the GetSection() method. According to the ASP.NET Core Configuration documentation you should use "ConnectionStrings:myConnectionString" instead of "ConnectionStrings.myConnectionString".
Plus, if you wish to retrieve the value directly you may prefer to use the GetValue() method instead:
var cs = _config.GetValue("ConnectionStrings:myConnectionString", "");
If you prefer, you can also use the index notation as:
var cs = _config["ConnectionStrings:myConnectionString"];
But I honestly find the first approach more clean and elegant as the GetValue() method allows you to specify a default value in case the property is not found in the configuration.
I would like to use Serilog for logging in .Net core 2.0 class library project. I have searched many places and did not find any example for integrating the Serilog in class library project. Can anybody refer a sample?
Thanks.
You should not set up Serilog logging inside of a class library. A class library is for consumption by other applications, for example an ASP.NET Core web application, or a console application or whatever. The class library is not the entry point of the application, so it should not be responsible for setting up application wide things like logging. It would also be very difficult to do so because a class library does not have a central entry point (by design), so where exactly would you expect to set logging up?
Instead, your library should simply rely on logging to be there and have a way to receive loggers when it needs them. If your application is built with dependency injection in mind, you can just inject your loggers where you need them.
It’s then the responsibility of the application entry point to set up logging and to provide your library with the logging infrastructure.
So if you are using this in an ASP.NET Core context, just follow the guidelines on how to set up Serilog with ASP.NET Core.
You can create a static class logger that is the logging configuration entry point on your class library, like this:
public static Microsoft.Extensions.Hosting.IHostBuilder UseGloabalLogger(this Microsoft.Extensions.Hosting.IHostBuilder app)
{
return app.UseSerilog((hostingContext, loggerConfiguration) => loggerConfiguration
.ReadFrom.Configuration(hostingContext.Configuration)
.WriteTo.File(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + "\\LOG\\"+string.Format("Logging-{0}.txt",DateTime.Now.ToString("yyyyMMdd")))
.WriteTo.Debug()
.WriteTo.Console(
outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties:j}{NewLine}{Exception}"));
}
then in your Program.cs of webApi o WebApp you must import your class library that reference serilog and initilize them with
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseGloabalLogger()
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
Best practices wants that any logging configuration must be inserted in your appsettings.json
"Serilog": {
"MinimumLevel": {
"Default": "Information",//or Error or any other
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
..................
}
}