I can't seem to get Trace level log information outputted after upgrading to .NET Core 2.0 (+ASP.NET Core 2.0).
In fact, if I do a dotnet new webproject and add the code below in Startup for Configure, I do not get any trace or debug log messages, but I get the Information and Error messages twice. Commenting out the .AddConsole()call will output these (Information and Error) only once - suggesting that it gets configured automatically with a console provider by default. Keep in mind, this is a "File -> New" project experience, there is nothing setup in Program.cs for logging or configuration at all for this - except for what I've added. Anyone seen things? Or should I register a GitHub issue for it.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Microsoft.Extensions.Logging.LogLevel.Trace);
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.Run(async (context) =>
{
var logger = loggerFactory.CreateLogger("Blah");
logger.LogTrace("Hello world : Trace");
logger.LogDebug("Hello world : Debug");
logger.LogInformation("Hello world : Information");
logger.LogError("Hello world : Error");
await context.Response.WriteAsync("Hello World!");
});
}
The way logging is configured has changed a little... The recommended way (and it's pretty well documented in this GitHub issue/announcement to do it now is to configure the loggers on the AddLogging method, such as
services.AddLogging(builder =>
{
builder.AddConfiguration(Configuration.GetSection("Logging"))
.AddConsole()
.AddDebug();
});
And have an appsettings.json like
Notice
Seems a few people are confused, because the example only demonstrates the configuration of Console provider and not all loggers.
The LogLevel section configures logging level for all namespaces (Default key) or for a specific namespace (System overrides the default value for all classes logging whose namespace starts with System.*.
This is for the class used in T in ILogger<T>). This allows to set a higher or lower than default logging level for loggers from this namespace.
{
"ApplicationInsights": {
"InstrumentationKey": ""
},
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Information",
"System": "Warning",
"Microsoft": "Information"
},
"Console": {
"LogLevel": {
"Default": "Warning",
"System": "Information",
"Microsoft": "Information"
}
}
}
}
Please note that the structure of the appsettings.json changed from what it used to be in .NET Core 1.x and that Logging entry in the appsettings.json now has logger provider names in it, which allows you to configure logging levels per logging provider.
Previously, the entry in appsettings.json would only be applicable to the console logger.
Alternatively, the logging can now be moved within the WebHostBuilder instead.
public static void Main()
{
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureAppConfiguration((hostingContext, config) =>
{
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddJsonFile("hosting.json", optional: false)
.AddEnvironmentVariables();
})
.ConfigureLogging((webhostContext, builder) => {
builder.AddConfiguration(webhostContext.Configuration.GetSection("Logging"))
.AddConsole()
.AddDebug();
})
.UseIISIntegration()
.UseStartup<Startup>()
.UseApplicationInsights()
.Build();
host.Run();
}
Update
In case one doesn't want to use the appsettings.json, one can register the filters in code too.
services.AddLogging(builder =>
{
builder.AddConfiguration(Configuration.GetSection("Logging"))
// filter for all providers
.AddFilter("System", LogLevel.Debug)
// Only for Debug logger, using the provider type or it's alias
.AddFilter("Debug", "System", LogLevel.Information)
// Only for Console logger by provider type
.AddFilter<DebugLoggerProvider>("System", LogLevel.Error)
.AddConsole()
.AddDebug();
});
I spent almost twenty minutes to realize that since Configuration.GetSection("Logging") in the Startup.cs file reads the section "Logging" from the config in the appsettings.json file, which was configured as "Error". Changing it to "Information" or anything lower, fixed the issue.
Here's what the appsettinsg.json file looks now:
{
"Logging": {
"IncludeScopes": true,
"Debug": {
"LogLevel": {
"Default": "Information"
}
},
"Console": {
"LogLevel": {
"Default": "Information"
}
}
}
}
To find out more about the levels of logging (such as in "Information"), check out this link, that also provides general information on ASP.NET Core logging.
I'm just posting here, just in case you bump into any trouble with getting the logging to work, make sure you've been through that JSON file.
Nothing of the above works for me
The only workaround was to write a method
private void ConfigLogging( ILoggingBuilder builder ) {
builder.SetMinimumLevel( LogLevel.Trace );
//... additional configuration...
}
and when using the AddLogging extension method write it as
services.AddLogging( ConfigLogging );
The following structure of appsettings.json seems to work fine:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"System": "Information",
"Microsoft": "Information"
},
"Console":
{
"IncludeScopes": true
}
}
}
Taken from https://learn.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-2.1
Also, see what your start up calls are, I find the following works for me:
public class Startup
{
public Startup(IHostingEnvironment env)
{
var logger = new LoggerConfiguration()
.MinimumLevel.Information()
.WriteTo.Sink(jsonSink)
.Enrich.WithExceptionDetails()
.CreateLogger();
Log.Logger = logger;
}
}
Related
I have a solution with 2 projects:
function app project
web api .net core 6.0 project
The function app is succesfully logging to app insights, but the web api project is not! Azure portal is showing that both of the projects are configured to write to the same instance of app insights.
Is it a problem that two different resources are writing to the same app insights instance? If not, what am I doing wrong?
To configure Application Insights with telemetry you need to configure both telemetry and logging independently. Manual configuration or convention based in config configuration can both be used:
https://learn.microsoft.com/en-us/azure/azure-monitor/app/asp-net-core?tabs=netcore6
Manually setting options when configuring DI:
public void ConfigureServices(IServiceCollection service)
{
// ...
ApplicationInsightsServiceOptions telemetryOptions = new ();
telemetryOptions.InstrumentationKey = YourInstrumentationKey;
// Can enable/disable adaptive sampling here.
// https://learn.microsoft.com/en-us/azure/azure-monitor/app/sampling
telemetryOptions.EnableAdaptiveSampling = false;
services.AddApplicationInsightsTelemetry(telemetryOptions);
services.AddLogging(logBuilder =>
{
logBuilder.AddApplicationInsights(YourInstrumentationKey)
// adding custom filter for specific use case.
.AddFilter("Orleans", (level) => level == LogLevel.Error);
});
// ...
}
When using appsettings.json:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ApplicationInsights": {
"ConnectionString": "Copy connection string from Application Insights Resource Overview"
}
}
Then DI is can be slightly simplified:
public void ConfigureServices(IServiceCollection service)
{
// ...
services.AddApplicationInsightsTelemetry();
services.AddLogging(logBuilder => logBuilder.AddApplicationInsights()});
// ...
}
I am starting a web api which uses postgres as the backend.
I am on a team of developers that will each have a local db for development. How can I ensure that if a new developer comes on the team that their local db is created without manually creating it themself.
As of right now, we each created our local db's through command line and update our appsettings.Development.json to use our local db connection string (which is on the gitignore incase we use sensitive passwords).
It's annoying to have to manually set this portion up however. Is there anyway to just have a database be created on the fly? As in, right when they launch the API, the db should be created and the migrations applied onto it.
appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"Local": "Server=localhost;Port=5432;Database=mydb;User ID=xxx;Password=xxx;"
}
}
Startup.cs
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
UpdateDatabase(app);
// Other configurations
}
public virtual void UpdateDatabase(IApplicationBuilder app)
{
using var serviceScope = app.ApplicationServices
.GetRequiredService<IServiceScopeFactory>()
.CreateScope();
using var context = serviceScope.ServiceProvider.GetService<MyDbContext>();
context.Database.EnsureCreated();
context.Database.Migrate();
}
Despite hours spent on google, I am not getting there. We have a Core 3.1 MVC Web App project, and I've been asked to use SeriLog to write logs to Azure Table Storage. For the life of me, I can't find a working example or tutorial online. Here's what I've done so far:
Added the following NuGet's:
Serilog
Serilog.Extensions.Logging
Serilog.Sinks.AzureTableStorage
In appsettings.json,I replaced this:
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Information",
"Microsoft.Hosting.Lifetime": "Warning"
}
With this:
"Serilog": {
"WriteTo": [
{
"Name": "AzureTableStorage",
"Args": {
"storageTableName": "Logs",
"connectionString": "DefaultEndpointsProtocol=https;AccountName=***;AccountKey=***;EndpointSuffix=core.windows.net"
}
}
]
},
And now I am stuck. This is currently in Program.cs in CreateHostBuilder :
.ConfigureLogging(logging =>
{
logging.AddConsole();
})
I assume I should replace this? But, with what? I am not sure where to go from here. The serilog-sinks-azuretablestorage page on Github isn't much help. And I've been unable to find anything via Google that explains how to finish the implementation.
Well, I didn't get any bites on this. But after reading about 5 different articles, I managed to figure it out. In Program.cs, this was there by default:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.AddConsole();
})
And I replaced it with this:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging((hostingContext, logging) =>
{
var logger = new LoggerConfiguration()
.ReadFrom.Configuration(hostingContext.Configuration)
.CreateLogger();
logging.AddSerilog(logger);
})
hostingContext is an instance of HostBuilderContext and it contains '.Configuration' which is an instance of IConfiguration. So hostingContext.Configuration contains all your settings in appsetting.json.
In addition to the NuGet packages I mentioned in the OP, I also had to add this one:
Serilog.Settings.Configuration
(It's amazing how sometimes it can take 7 or 8 hours to write 4 lines of code.)
Add Serilog.Settings.Configuration and Microsoft.Extensions.Logging nuget package to your project it helps to read serilog configuration settings from appsettings.json and ensure you have below Serilog config in your Sartup.cs file.
public Startup(IConfiguration configuration)
{
Configuration = configuration;
//logger config
var logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.CreateLogger();
logger.Information("Logging configured");
Log.Logger = logger;
}
public void ConfigureServices(IServiceCollection services)
{
services.AddOptions();
services.AddLogging(loggingBuilder =>
{
loggingBuilder.AddConfiguration(Configuration.GetSection("Logging"));
loggingBuilder.AddConsole();
loggingBuilder.AddDebug();
//Add Serilog config to logbuilder
loggingBuilder.AddSerilog(Log.Logger);
});
}
//Add this config in appsettings.json
"Serilog": {
"Using": [ "Serilog.Sinks.AzureTableStorage" ],
"WriteTo": [
{
"Name": "AzureTableStorage",
"Args": {
"storageTableName": "MyAppLogs
"connectionString": ""
}
}
],
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
"Properties": {
"Application": MyApp
}
},
I want to be able to configure the nested levels like Microsoft.AspNetCore.Mvc/DataProtection independently of just Microsoft.*, is this possible, if so how do I do it?
The logging works and I see currently see everything at debug but nothing is excluded.
I'm injecting the settings etc into a class which is configured in Program.cs like this
var builder = new ConfigurationBuilder().SetBasePath(Environment.CurrentDirectory);
builder.AddJsonFile("appsettings.json", true, true);
var envName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
if (string.IsNullOrWhiteSpace(envName))
builder.AddJsonFile($"appsettings.${envName}.json", true);
builder.AddEnvironmentVariables();
builder.AddCommandLine(args);
var configurationRoot = builder.Build();
new WebHostBuilder()
.UseKestrel(options =>
{ options.Limits.MaxRequestBodySize = null; })
.UseContentRoot(Directory.GetCurrentDirectory())
.UseConfiguration(configurationRoot)
.ConfigureLogging(lb =>
{
lb.AddConsole();
lb.AddDebug();
lb.SetMinimumLevel(LogLevel.Trace);
})
.UseStartup<Startup>()
.UseIISIntegration()
.Build()
.Run();
with Startup.cs injecting the logger and config like
public Startup(ILogger<Startup> iLogger, IConfiguration iConfiguration)
{
_configuration = iConfiguration;
_logger = iLogger;
_logger.LogDebug("Configured logger, config and builder.");
}
with logging config in appsettings.json like
"Logging": {
"IncludeScopes": true,
"LogLevel": {
"Microsoft.AspNetCore.Mvc": "Warning",
"Microsoft.AspNetCore.DataProtection": "Warning",
"Default": "Debug"
}
}
Coming from log4j I'd attempt something like the above but it's not working, where have I gone wrong?
You need to read the how to setup a host page to understand what needs to go into the program.cs code. This has changed for .Net Core 2.x and has reduced the amount of code we need to load the settings and setup logging.
In ASP.NET Core 2.0 we have this
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
That CreateDefaultBuilder(args) has many helpful defaults. However it contains this:
.ConfigureLogging((context, logging) => {
logging.AddConfiguration(context.Configuration.GetSection("Logging"));
logging.AddConsole(); // HERE IS THE PROBLEM
logging.AddDebug(); // HERE IS THE PROBLEM
})
So the console and debug logging providers are always registered.
I used to register them like this
if (env.IsDevelopment())
{
// register them here
}
How do I remove/unregister them when running in production mode? I don't mean changing the logging level, I mean I don't want them registered at all in production mode.
I would say the designed way to do this would be by changing the logging configuration not to log anything to those providers. But I understand that you want to remove any calls for production; and you can still do this properly in code.
You can simply access the hosting environment from the HostBuilderContext that gets passed to the ConfigureLogging lambda:
.ConfigureLogging((context, logging) =>
{
logging.AddConfiguration(context.Configuration.GetSection("Logging"));
if (context.HostingEnvironment.IsDevelopment())
{
logging.AddConsole();
logging.AddDebug();
}
});
Obviously, this alone does not help to undo what the CreateDefaultBuilder call already set up. First, you would need to unregister those providers. For that, you can use the new ILoggingBuilder.ClearProviders method:
.ConfigureLogging((context, logging) =>
{
// clear all previously registered providers
logging.ClearProviders();
// now register everything you *really* want
// …
});
This was introduced in response to this logging issue on GitHub.
I found that it is better to remove a specific logging provider from the services as follows:
.ConfigureLogging((context, logging) => {
foreach (ServiceDescriptor serviceDescriptor in logging.Services)
{
if (serviceDescriptor.ImplementationType == typeof(Microsoft.Extensions.Logging.Console.ConsoleLoggerProvider))
{
// remove ConsoleLoggerProvider service only
logging.Services.Remove(serviceDescriptor);
break;
}
}
// now you can register any new logging provider service; e.g.,
logging.AddLog4Net();
logging.AddEventSourceLogger();
})
I think you cant use the CreateDefaultBuilder then or set the LogLevels to None maybe. According to the docs you can use this.
public static void Main(string[] args)
{
var webHost = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureAppConfiguration((hostingContext, config) =>
{
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true,
reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json",
optional: true, reloadOnChange: true);
config.AddEnvironmentVariables();
})
.ConfigureLogging((hostingContext, logging) =>
{
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddConsole();
logging.AddDebug();
})
.UseStartup<Startup>()
.Build();
webHost.Run();
}
How to Add providers Section https://learn.microsoft.com/en-us/aspnet/core/fundamentals/logging?tabs=aspnetcore2x
Found another option, just add a Logging Filter for Console in your appsettings.json
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
},
"Console": {
"LogLevel": {
"Default": "None"
}
}
}