c# core Microsoft.Extensions.Logging and Log Config - c#

I have a small console app. I have enabled Debug and Console logging. However, they do not seem to be honouring my config for log level. Here is my setup:
Add Config file and create logger
// global to Program
private static ILogger<Program> _logger;
private const string _configFile = "appsettings.json";
//inside Main
_config = new ConfigurationBuilder()
.AddJsonFile(_configFile, optional: false, reloadOnChange: true)
//.AddEnvironmentVariables()
.AddCommandLine(args)
.Build();
using var loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddDebug();
builder.AddSimpleConsole();
});
_logger = loggerFactory.CreateLogger<Program>();
appconfig.json
"Logging": {
"IncludeScopes": true,
"LogLevel": {
"Default": "Debug",
"Microsoft": "Warning"
},
"Debug": {
"LogLevel": {
"Default": "Trace",
"Microsoft": "Warning",
"FleetLogix.TcaProcessor": "Trace"
}
},
"SimpleConsole": {
"IncludeScopes": "false",
"SingleLine": "false",
"TimestampFormat": "yyyy-MM-dd HH:mm:ss ",
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"FleetLogix.TcaProcessor": "Information"
}
}
},
Its currently set to log to two providers, Debug (visual studio run pane) and Console. This is working. Debug is meant to log at Trace, but is only logging at Info. Console is logging at Info, but is not prefixing the timestamp onto the messages.
Is my config setup correctly? (correct property names, correct depth, etc)
What should I change it to?
Console also has the awful line break that reading tells me you need to fork Microsoft.Extensions.Logging.Console to fix, so another day. :/

I know you've moved on to Serilog, but the answer here is that you're not connecting the config up to the LoggerFactory. You need to identify the config object and also which section to load logging settings from, using the .AddConfiguration extension method from Microsoft.Extensions.Configuration:
using Microsoft.Extensions.Configuration;
var loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddConfiguration(_config.GetSection("Logging"));
builder.AddDebug();
builder.AddSimpleConsole();
});
This question is similar:
.NET Non-host LoggerFactory configuration

I ended up switching to Serilog as I needed a file writer anyway. The only hard part was working out the differences between the older and current version, where rollingfile sink has now been integrated into file sink
Program.cs
#region Initialise Logger
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(_config)
.CreateLogger();
Log.Information("Logger started");
#endregion
appsettings.json
"Serilog": {
"Using": [
"Serilog.Sinks.Console",
"Serilog.Sinks.File"
],
"MinimumLevel": "Debug",
"WriteTo": [
{
"Name": "Console"
},
{
"Name": "File",
"Args": {
"path": "c:\\scripts\\log\\myprogram.log",
"rollingInterval": "Day",
"retainedFileCountLimit": 7
}
}
],
"Properties": {
"Application": "MyProgram"
}
},

Related

Application Insights not working in locally running Azure Worker Function

I am trying to get app insights to work in a local .NET 7 Worker Azure Function
public class Tools
{
public Tools(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger<Tools>();
}
[Function("test-app-insights")]
public async Task<IActionResult> TestAppInsightsAsync([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "tools/test-app-insights")]
HttpRequest req)
{
_logger.LogInformation("HELLOFROMNEWFUNCTION");
await Task.Yield();
var response = 0;
var okResponse = new OkObjectResult(response);
return okResponse;
}
}
I have added the code below to configure services but nothing is shown in App Insights, and there are no errors
var appInsightsConnectionString = "MY CONNECTION STRING";
services.AddApplicationInsightsTelemetryWorkerService((a =>
{
a.EnableAdaptiveSampling = false;
a.ConnectionString = appInsightsConnectionString;
}));
Does anyone know what I have missed?
I have this in the logging section of my host.json
"logging": {
"logLevel": {
"default": "Information",
"Microsoft": "Warning",
"System": "Warning",
"Host": "Error",
"Function": "Error",
"Host.Aggregator": "Information"
},
"Serilog": {
"MinimumLevel": "Information",
"WriteTo": [
{
"Name": "Console",
"Args": {
"outputTemplate": "{Timestamp:HH:mm:ss} {Level} | {RequestId} - {Message}{NewLine}{Exception}"
}
}
]
},
"applicationInsights": {
"samplingSettings": {
"isEnabled": true
}
}
},
Paul
Create Application Insights Instance and copy the Instrumentation key for later use.
Create a Function App.
Enable Application Insights option while creating the Function App.
Select the Application Insights which we have created in the previous step.
Make sure that the region of Application Insights and Function App are same.
InstrumentationKey will be added in the Application Settings automatically once we enable the ApplicationInsights.
In Visual Studio, Create a Function App with .NET 7 Isolated.
My host.json:
{
"version": "2.0",
"logging": {
"applicationInsights": {
"samplingSettings": {
"isEnabled": true,
"excludedTypes": "Request"
}
}
}
}
My local.settings.json:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated",
"APPINSIGHTS_INSTRUMENTATIONKEY": "Copy from Application Insights "
}
}
My Traces in Azure Application Insights Instance:

Add custom ILogger to ASP.NET Core Web API

I have a central Project which generates all the Loggers for the subprojects. (And does a lot of other stuff which is not nessesary for my problem)
One of the Subprojects is an ASP.NET Web API. Now I want to add the Logger which is generated by a Logger Factory (see below) to the WebApplication. The problem is that the current version of WebApplication doesn't accept ILoggers...
(I use .Net 6)
The following function generates my Logger Factory:
private ILoggerFactory CreateLoggerFactory()
{
IConfiguration configSerilog = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", false, false)
.Build();
Serilog.Core.Logger serilogLogger = new LoggerConfiguration()
.ReadFrom.Configuration(configSerilog)
.Enrich.WithProperty("ComponentShortcuts", _componentShortcuts)
.CreateLogger();
ILoggerFactory loggerFactory = new LoggerFactory()
.AddSerilog(serilogLogger);
return loggerFactory;
}
The only thing I can do at the moment is to delete the default Loggers:
var builder = WebApplication.CreateBuilder();
builder.Logging.ClearProviders();
The problem is that I don't know how to add my Logger, because there is no AddLogger() function.
(I have no idea how to convert the ILogger or if there is something else that I can generate with the Logger Factory that helps me.)
I hope you can help me :)
So I faced this same issue 2 days ago with logging in .net 6 web api. And I found a solution to it that worked for me, i-e; By using LoggerConfiguration.
Although I'm still looking for a way to do it by LoggerFactory I'll post it as soon as I figure it out. Till then I hope this helps you.
Here's my code;
Program.cs
builder.Logging.ClearProviders();
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
var logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
//.MinimumLevel.Override("Microsoft", LogEventLevel.Error)
//.MinimumLevel.Override("Microsoft.AspNetCore",LogEventLevel.Error)
//.MinimumLevel.Override("Serilog", LogEventLevel.Error)
.Enrich.FromLogContext()
.Enrich.WithClientIp("CF-Connecting-IP")
.Enrich.WithClientAgent()
.CreateLogger();
Log.Logger = logger;
builder.Logging.AddSerilog(logger);
builder.Host.UseSerilog();
Then add the middleware
app.UseSerilogRequestLogging();
appsettings.json (I'm logging to Console and Sql Server also (In case you want to do it.))
"Serilog": {
"Using": [ "Serilog.Enrichers.ClientInfo", "Serilog.Sinks.MSSqlServer" ],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Warning",
"System": "Warning",
"System.Net.Http.HttpClient": "Warning"
}
},
"Enrich": [
"FromLogContext",
"WithMachineName",
"WithClientIp",
"WithClientAgent",
{
"Name": "WithClientIp",
"Args": {
"xForwardHeaderName": "CF-Connecting-IP"
}
}
],
"WriteTo": [
{
"Name": "Console"
},
{
"Name": "MSSqlServer",
"Args": {
"connectionString": "",
"sinkOptionsSection": {
"tableName": "TableName",
"autoCreateSqlTable": true
},
"restrictedToMinimumLevel": "Information",
"columnOptionsSection": {
"primaryKeyColumnName": "",
"addStandardColumns": [ "LogEvent", "SourceContext" ],
"additionalColumns": [
{
"ColumnName": "ClientIPAddress",
"PropertyName": "UserIp",
"DataType": "nvarchar"
}
]
}
}
}
]
}
Feel free to let me know if you have any doubts. And don't forget to install the relevant nuget packages.
All the best!! :)

Combine Serilog logs with built-in Microsoft .NET Core loggers

I have a Windows Service written in .NET Core 6 and have been using the default logging solution, including Microsoft's Event Log logger extension, which is working well. My current Program.cs which sets up the host and changes the Event Log's source name is:
using Microsoft.Extensions.Logging.EventLog;
using System;
IHost host = Host.CreateDefaultBuilder(args)
.UseWindowsService(options =>
{
options.ServiceName = "My Super Service";
})
.ConfigureServices(services =>
{
services.AddHostedService<Worker>();
services.Configure<EventLogSettings>(settings =>
settings.SourceName = "My Super Service");
services.AddSingleton<SomeOtherServiceHere>();
})
.Build();
await host.RunAsync();
I use ILogger Dependency Injection in the service's Worker class and my SomeOtherServiceHere code without issue.
My appsettings.json includes setting the Event Log's LogLevel to Information just so I can see some startup info during testing:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.Hosting.Lifetime": "Warning"
},
"EventLog": {
"LogLevel": {
"Default": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
}
Microsoft doesn't include a file-based logger in .NET Core, so I've added Serilog into the mix. The file logger and console logger are working, but I'm not seeing Event Log entries any more from the Microsoft logger.
The addition to my Program.cs CreateBuilder call is:
.UseSerilog((context, config) => config
.ReadFrom.Configuration(context.Configuration)
.Enrich.FromLogContext()
.WriteTo.Console())
I've added a new Serilog section to my appsettings.json to configure the file log:
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"WriteTo": [
{
"Name": "File",
"Args": { "path": "./logs/log.txt", "rollingInterval": "Day" }
}
]
}
Is it possible to use Microsoft's extension for Event Log logging and Serilog for everything else? Or is it recommended that I abandon this approach and use the Serilog Event Log Sink instead? I'm a little reticent to do this because configuring it via appsettings.json is under-documented and I'd rather not change what's already working.

Sentry configuration in appsettings.json with Serilog in .Net Core 3 Console App

I'm using the following code to configure Sentry with Serilog in my .Net Core Console application:
return new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Sentry(o =>
{
o.MinimumBreadcrumbLevel = LogEventLevel.Error;
o.MinimumEventLevel = LogEventLevel.Error;
o.Dsn = new Dsn(configuration.GetValue<string>("Sentry:Dsn"));
o.Debug = false;
o.AttachStacktrace = true;
o.SendDefaultPii = true;
})
.CreateLogger();
Now I would like to move all this configuration in the appsettings.json file because I need to have a different configuration in Develop environment and Production:
Example:
"Sentry": {
"Dsn": "<dsn>",
"IncludeRequestPayload": true,
"IncludeActivityData": true,
"Debug": false,
"DiagnosticsLevel": "Debug",
"MinimumBreadcrumbLevel": "Debug",
"MinimumEventLevel": "Warning"
},
Is it possible to read the whole configuration from there?
update
I try the following configuration in my Console application:
static void Main(string[] args)
{
using (SentrySdk.Init("<dsn>"))
{
// my code
}
...
serviceCollection.AddSingleton<ILogger>(s =>
{
return new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.CreateLogger();
});
appsettings:
"Serilog": {
"Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.Sentry" ],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Warning",
"Sentry": "Information"
}
},
"Enrich": [ "FromLogContext" ],
"WriteTo": [
{
"Name": "Console"
},
{
"Name": "Sentry",
"Args": {
"Dsn": "<dsn>",
"MinimumBreadcrumbLevel": "Info",
"MinimumEventLevel": "Info",
"AttachStackTrace": true,
"Debug": true,
"DiagnosticsLevel": "Info"
}
}
]
But SentrySdk.Init("<dsn>") needs a DSN and it won't read it from appsettings!
Is this the way?
Serilog is unaware of the ASP.NET Core configuration. At least in a way that would bind specific sections of the configuration object to its extensions.
If you're using ASP.NET Core, I assume you're also using Sentry.AspNetCore. It's advised you do. In which case you'd need to pass configuration to it too.
NuGetTrends which is an open source project uses Serilog with ASP.NET Core while using the appsettings.json file to configure things.
Here's the Program.cs setting up Sentry, Serilog and ASP.NET Core.
Note that the configuration as you mentioned (with Sentry as a key) will be picked up by Sentry.AspNetCore but not by Sentry.Serilog (which is decoupled from ASP.NET Core).
You can configure the latter, which is a normal Serilog sink like:
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Warning",
"Sentry": "Information"
}
},
"WriteTo": [
{
"Name": "Sentry",
"Args": {
"MinimumBreadcrumbLevel": "Debug",
"MinimumEventLevel": "Warning"
}
}
],
"Enrich": [ "FromLogContext", "WithMachineName" ]
}
I suggest leaving the DSN and other settings as you did, on the Sentry key, which makes the ASP.NET Core initialize the SDK, it will also leverage the Serilog integration.

Serilog setup for Asp.Net Core 2.0.1 not producing logs

I am trying to set up Serilog as my logger in a multi project solution using Asp.Net Core 2.0.1, EF 2.0.1 and MVC 6.
I have set up Serilog, mostly following the guidelines from this blog post
Set up Serilog post
There is a problem with the json in that post, which I've corrected and is shown here
appsettings.json file
{
"ApplicationConfiguration": {
"ConnectionStrings": {
"DevelopmentConnection": "Server=(localdb)\\mssqllocaldb;Database=TestingConfigurationNetCoreTwo_Development;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"ApplicationInfo": {
"VersionNumber": "1.0.0",
"Author": "Jimbo",
"ApplicationName": "CustomTemplate",
"CreatedOn": "November 20, 2017"
},
"Serilog": {
"Using": [
"Serilog.Sinks.RollingFile",
"Serilog.Sinks.Async",
"Serilog.Sinks.ApplicationInsights",
"Serilog.Sinks.Console",
"Serilog.Sinks.Seq"
],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning"
}
},
"WriteTo": [
{
"Name": "Async",
"Args": {
"configure": [
{
"Name": "RollingFile",
"Args": { "pathFormat": "Logs/log-{Date}.log" }
}
]
}
}
],
"Enrich": ["FromLogContext", "WithMachineName", "WithThreadId"],
"Properties": {
"Application": "CustomTemplate"
}
}
}
}
I have the logger configuration work in the Main method of Program.cs
public static int Main(string[] args)
{
var currentEnv = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{currentEnv}.json", optional: true)
.AddEnvironmentVariables()
.Build();
//Configure logger
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
//do this for now
//TODO:figure out how to add to Serilog config in appsettings.json
.WriteTo.Seq("http://localhost:5341")
.CreateLogger();
Log.Information("Logger created");
try
{
Log.Information("Starting web host");
BuildWebHost(args).Run();
return 0;
}
catch (Exception ex)
{
Log.Fatal(ex, "Web Host terminated unexpectedly");
return 1;
}
finally
{
Log.CloseAndFlush();
}
//BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
And in my Startup method
services.AddLogging(loggingBuilder =>
loggingBuilder.AddSerilog(dispose: true));
I was assuming Serilog would create the Logs folder once I ran the application, but no Log folder or logs. I added a Logs folder to both the root of the solution, and the web app project and ran it again. No logs. The blog post author suggested looking in the machines root folder. I looked both in C and OneDrive main folders (Solution Files stored on OneDrive) but there were no logs there either.
I then noticed a stack trace warning
System.IO.FileNotFoundException occurred
HResult=0x80070002
Message=The configuration file 'appsettings.json' was not found and is not optional. The physical path is 'C:\Users\OneDrive\TestingConfigurationAspNetCore2\TestMvcApp\bin\Debug\netcoreapp2.0\appsettings.json'.
Source=
StackTrace:
at Microsoft.Extensions.Configuration.FileConfigurationProvider.Load(Boolean reload)
at Microsoft.Extensions.Configuration.FileConfigurationProvider.Load()
at Microsoft.Extensions.Configuration.ConfigurationRoot..ctor(IList`1 providers)
at Microsoft.Extensions.Configuration.ConfigurationBuilder.Build()
I was getting this warning before, which is why I added the set bath path method in the configuration set up, because the application was failing at the code line
.AddJsonFile("appsettings.json")
which was fairly obvious because in the bin folder the file isn't called appsettings.json, its called TestMvcApp.runtimeconfig.json.
Once I added .SetBasePath, the code ran through so I put a breakpoint after the configuration setup. The configuration object contains all the settings from my appsettings.json file, so why I am getting that stack trace error? I don't know but I'll bet a dollar it is why there are no logs (no log messages appear in the console either)
Any help on why the stack trace error or why there are no log messages being written to the log file or displayed on the console would be most appreciated.
which was fairly obvious because in the bin folder the file isn't
called appsettings.json, its called TestMvcApp.runtimeconfig.json.
TestMvcApp.runtimeconfig.json is not your appsettings.json, it's a runtime configuration file as it's clear from the file name.
I bet that your appsettings.json is just not copied to the output directory during the build. To fix that select appsettings.json in Visual Studio Solution explorer, in context menu select properties and set 'Copy to Output Directory' to 'Copy always' or 'Copy if newer':
Also your json configuration has several issues:
Serilog section should not be inside ApplicationConfiguration section. It should be on the same level, i.e top-level section.
You also has suspicious WriteTo section with one sink (RollingFile) inside another (Async). Check here sample json configuration for Serilog.
In order to use all those sinks (Serilog.Sinks.RollingFile, Serilog.Sinks.Console) you should install corresponding sink NuGets: Serilog.Sinks.RollingFile, Serilog.Sinks.Console, etc.
Here is configuration file (with RollingFile sink only) that works fine for me:
{
"ApplicationConfiguration": {
"ConnectionStrings": {
"DevelopmentConnection": "Server=(localdb)\\mssqllocaldb;Database=TestingConfigurationNetCoreTwo_Development;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"ApplicationInfo": {
"VersionNumber": "1.0.0",
"Author": "Jimbo",
"ApplicationName": "CustomTemplate",
"CreatedOn": "November 20, 2017"
}
},
"Serilog": {
"Using": [
"Serilog.Sinks.RollingFile"
],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning"
}
},
"WriteTo": [
{
"Name": "RollingFile",
"Args": { "pathFormat": "c:\\log-{Date}.log" }
}
],
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
"Properties": {
"Application": "CustomTemplate"
}
}
}
The accepted answer only logged some messages for my project. I'm not sure why. Ondrej Balas's approach worked better for me.
Install these Nuget packages:
Serilog
Serilog.AspNetCore
Serilog.Settings.Configuration
Serilog.Sinks.Console
Serilog.Sinks.RollingFile
Program.cs needs .UseSerilog() added:
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureLogging((hostingContext, logging) =>
{
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
})
.UseStartup<Startup>()
.UseSerilog()
.Build();
Startup.cs needs a couple of changes
one in the constructor:
public Startup(IConfiguration configuration)
{
Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(configuration).CreateLogger();
Configuration = configuration;
}
another in Configure():
loggerFactory.AddSerilog();
if (env.IsDevelopment())
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
}
appsettings.json needs a Serilog config entry in root:
"Serilog": {
"Using": [ "Serilog.Sinks.Console" ],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"WriteTo": [
{ "Name": "Console" },
{
"Name": "RollingFile",
"Args": {
"pathFormat": "logs\\log-{Date}.log",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] [{SourceContext}] {Message}{NewLine}{Exception}"
}
}
],
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
"Properties": {
"Application": "My Application"
}
}

Categories