Serilog seems to be ignoring log level when deployed - asp.net-core

We have serilog enabled for our .net6 web apps, and deployed within Azure App Services, to log to Elastic
Locally, the log levels appear to be adhered to, but when we deploy to Azure, it just seems to be ignored and log Information and Debug messages, and not use the min log level that was actually set.
The Program.cs is as so:
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Serilog;
using System;
using System.IO;
using System.Threading.Tasks;
namespace MyApp
{
public class Program
{
public async static Task<int> Main(string[] args)
{
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables()
.Build();
Serilog.Debugging.SelfLog.Enable(message => Console.WriteLine(message));
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.CreateLogger();
try
{
Log.Information("Starting");
await CreateHostBuilder(args).Build().RunAsync();
return 0;
}
catch (Exception ex)
{
Log.Fatal(ex, $"host terminated unexpectedly {ex}");
return 1;
}
finally
{
Log.CloseAndFlush();
}
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.UseSerilog();
}
}
And the Serilog section with AppSettings.json
"Serilog": {
"Using": ["Serilog.Sinks.Console", "Serilog.Sinks.Elasticsearch"],
"MinimumLevel": {
"Default": "Debug",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"WriteTo": [
{
"Name": "Console",
"Args": {
"theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console",
"outputTemplate": "[{Timestamp} {Level:u3}] {Message:lj} <s:{SourceContext}>{NewLine}{Exception}"
}
},
{
"Name": "Elasticsearch",
"Args": {
"nodeUris": "https://<<<ELASTICHOST>>>",
"indexFormat": "logs-{0:yyyy.MM.dd}",
"connectionGlobalHeaders": "Authorization=ApiKey <<<KEY>>>>;",
"emitEventFailure": "WriteToSelfLog",
"autoRegisterTemplate": true,
"registerTemplateFailure": "IndexAnyway",
"autoRegisterTemplateVersion": "ESv7",
"batchPostingLimit": 50,
"batchAction": "Create",
"period": 2,
"inlineFields": true,
"deadLetterIndexName": "deadletter-{0:yyyy.MM.dd}"
}
}
],
"Enrich": ["FromLogContext"],
"Properties": {
"Application": "MyAzureAppServiceApp",
"Environment": "Live"
}
}
The settings in the specific app service are as so:
Serilog__MinimumLevel__Default = Warning
Serilog__MinimumLevel__Override__Microsoft = Warning
Serilog__MinimumLevel__Override__System = Warning

I assume that by
it just seems to be ignored
you mean that you cannot see it in Application Insigths logs correct?
In order to see logs in Application Insigths logs you have to use Serilog.Sinks.ApplicationInsights.
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables()
.WriteTo.ApplicationInsights("InstrumentationKeyHere", TelemetryConverter.Traces, restrictedToMinimumLevel: LogEventLevel.Error)
.Build();
I modified your code and added one line. The added line tells Serilog to treat your log as Application Insigtht log traces.

Related

Serilog not logging in .net core 6 upgraded from 3.1

i upgraded my .net core 3.1 api to .net 6. i use console and file sinks of serilog but my custom logs from my controller do not get to the log sinks. other logs from the application pipeline get to the file.
all logs worked in version 3.1 and i have not made any changes to my program.cs which looks like
` public static void Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(Configuration)
.Enrich.FromLogContext()
.CreateLogger();
try
{
Log.Information("Starting web host");
CreateWebHostBuilder(args)
.UseIISIntegration()
.Build()
.Run();
}
catch (Exception ex)
{
Log.Fatal(ex, "API Host terminated unexpectedly");
}
finally
{
Log.CloseAndFlush();
}
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.UseSerilog();`
i've checked the serilog configuration and it looks ok. i am wondering i need to change the entire program.cs to conform with .net 6 for serilog to work. i am using serilog 3.4.
this is my serilog config:
"Serilog": {
"Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
"MinimumLevel": {
"Default": "Information"
},
"WriteTo": [
{
"Name": "Console",
"Args": {
"outputTemplate": "===> {Timestamp:HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}"
}
},
{
"Name": "File",
"Args": {
"path": "/tmp/logs/xxxx.json",
"formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact",
"rollingInterval": "Day",
"outputTemplate": "===> {Timestamp:HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}"
//"retainedFileCountLimit": 10
//"fileSizeLimitBytes": 2048
}
}
]
},

Serilog 3.4 and ASPNET core 2.1 stops logging after 3 lines when initialized through configuration

I am integrating Serilog into an existing aspnet core 2.1 WebHost app. My single dependency is Serilog.AspNetCore Version 3.4.0.
When I initialize the logger using configuration in WebHost builder, I get 3 lines in the log file and no other logging. When I initialize the logger completely in code in main, logging works as expected.
Serilog initialization through configuration (only 3 lines output):
appsettings.json:
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"Using": [ "Serilog.Sinks.File" ],
"WriteTo": [
{
"Name": "File",
"Args": {
"outputTemplate": "[{Level}] {Timestamp:yyyy-MM-ddTHH:mm:sszzz} - {Message:lj}{NewLine}{Exception}",
"path": "/var/log/somedir/somefile.log"
}
}
]
}
The builder code:
WebHost.CreateDefaultBuilder(args)
.UseSerilog((hostingContext, loggerConfiguration) =>
loggerConfiguration
.ReadFrom.Configuration(hostingContext.Configuration))
Serilog initialization in main (logging works as expected):
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.MinimumLevel.Override("System", LogEventLevel.Warning)
.Enrich.FromLogContext()
.WriteTo.File("/var/log/somedir/somefile.log", outputTemplate:"[{Level}] {Timestamp:yyyy-MM-ddTHH:mm:sszzz} - {Message:lj}{NewLine}{Exception}")
.CreateLogger();
try
{
Log.Information("Some service is starting");
CreateWebHostBuilder(args).Build().Run();
return 0;
}
catch(Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly");
return 1;
}
finally
{
Log.CloseAndFlush();
}
Code in the builder:
WebHost.CreateDefaultBuilder(args)
.UseSerilog()
Note that I'm pretty sure configuration is being read or the output would not be in the file specified in configuration.
Could the Microsoft logging stuff be smashing the Serilog stuff?
Can anyone spot what I'm doing wrong?

Serilog Logger - Requested value 'True' was not found

I'm getting this error when calling calling Serilog.Log.Logger():
This is .NET Core 2.1
System.ArgumentException: Requested value 'True' was not found.
My Program.cs:
public class Program
{
private static IConfiguration Configuration => new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", false, true)
.AddJsonFile(
$"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json",
true, true)
.AddEnvironmentVariables()
.Build();
public static void Main(string[] args)
{
Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(Configuration).CreateLogger();
try
{
Log.Information("Web hosting is starting up.");
CreateWebHostBuilder(args).Build().Run();
}
catch (Exception ex)
{
Log.Fatal(ex, "A fatal exception has forced unexpected host termination.");
throw;
}
finally
{
Log.Information("Web hosting is shutting down.");
Log.CloseAndFlush();
}
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*",
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft.EntityFrameworkCore": "Warning",
"Microsoft.AspNetCore.StaticFiles": "Warning"
}
},
"WriteTo": [
{
"Name": "Elasticsearch",
"Args": {
"nodeUris": "https://XXXXXXXXXXXXXX.com",
"indexFormat": "log-XXXXXXXXXX-{0:yyyy.MM.dd}",
"autoRegisterTemplate": true,
"autoRegisterTemplateVersion": true
}
}
],
"Enrich": [
"FromLogContext",
"WithMachineName",
"WithEnvironmentUserName"
],
"Properties": {
"Application": "{myappname}"
}
}
Here are the packages used installed on in this project (excuse the screenshot)
C:\repos\myapp\myapp>dotnet list package
Project 'myapp' has the following package references
[netcoreapp2.1]:
Top-level Package Requested Resolved
> BuildBundlerMinifier 3.2.435 3.2.435
> Microsoft.AspNetCore.App (A) [2.1.1, ) 2.1.1
> Microsoft.AspNetCore.Razor.Design 2.1.2 2.1.2
> Microsoft.NETCore.App (A) [2.1.0, ) 2.1.0
> Serilog.AspNetCore 3.2.0 3.2.0
> Serilog.Enrichers.Environment 2.1.3 2.1.3
> Serilog.Sinks.Elasticsearch 8.0.1 8.0.1
"autoRegisterTemplateVersion": true
The issue relates the autoRegisterTemplateVersion argument in the appsettings.json file.
From the Serilog.Sinks.Elasticsearch JSON appsettings.json configuration, we can see the autoRegisterTemplateVersion argument should be a string type:
After changing the autoRegisterTemplateVersion argument value from true to "ESv2", the issue disappears.

Is force logging available in Microsoft.Extensions.Logging

I have ASP.NET Core application. I am using Microsoft.Extensions.Logging.ILogger interface with Serilog logging provider.
In production environment, the log level is set to Error. So anything below Error loglevel will not get logged.
Is there Force logging available in Microsoft.Extensions.Logging, which would log the message regardless of what the loglevel is set?
Basically I want to log some information (temporarily) without setting LogLevel to Information because that would log all other unrelevant information messages.
Update 1
So i updated my appsettings.json as per the suggestion however that did not work. Note that serilog also has its own loglevel which i have commented out. But Still not working.
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Error",
"MyUserService": "Information"
}
},
"Serilog": {
"Using": [ "Serilog.Sinks.MSSqlServer" ],
//"MinimumLevel": "Error",
"WriteTo": [
{
"Name": "MSSqlServer",
"Args": {
//"restrictedToMinimumLevel": "Error",
"connectionString": "Data Source=.\\SQLExpress;Initial Catalog=MyDataBase;Integrated Security=True;MultipleActiveResultSets=True",
"tableName": "Logs"
}
}
],
"Properties": {
"Application": "MyApplication"
}
}
and then in MyUserService
public class MyUserService : BaseService, IMyUserService
{
private readonly ILogger<MyUserService> _logger;
public MyUserService(MyDBContext dbContext, ILogger<MyUserService> logger)
: base(dbContext)
{
_logger = logger;
}
public async Task DoSomethig()
{
_logger.LogInformation("Log something meaningful here");
}
}
and in program.cs
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseApplicationInsights()
.UseUrls("http://*:40006")
.ConfigureAppConfiguration((hostingContext, config) =>
{
//removed for brevity
})
.ConfigureLogging((hostingContext, logging) =>
{
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(hostingContext.Configuration)
.CreateLogger();
logging.AddSerilog();
})
.Build();
The idea is to configure the log level per log cagtegory.
Once you let yourself inject an ILogger<MyCategory> (where MyCategory can be any type - a special type just to indicate log categories or just the class you log from), you can configure the log level independent of everything else:
"Logging": {
"LogLevel": {
"Default": "Error",
"MyCategory": "Information"
}
}

Date and time in console log

Is their a way to mention the date and time in the console log of an asp.net core 2.0 project for production and development environment?
I have following in my startup:
services.AddLogging(builder =>
{
builder.AddConfiguration(Configuration.GetSection("Logging"+Environment.EnvironmentName))
.AddConsole()
.AddDebug();
});
Appsettings.json:
"LoggingDevelopment": {
"IncludeScopes": false,
"Console": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
},
"LoggingProduction": {
"IncludeScopes": false,
"Console": {
"LogLevel": {
"Default": "Error",
"System": "Error",
"Microsoft": "Error"
}
}
},
Current [development] log layout (without a date or time of the log line):
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
Executed action a.Controller (project) in 531.2457ms
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 532.5812ms 200 text/html; charset=utf-8
A date and time would be extremly handy in production mode for error lines.
Default Console logger is pretty limited. Of course there is always the possibility to use lambda formatter like said in Github issue provided by serpent5. But it's accessible only if using raw ILogger.Log() method.
It's not available for ILogger extensions like LogInformation or LogError. This option is also not available if you don't control logging call. It's actually your case when logging is done by ASP.NET Core internal classes.
So you need some more flexible implementation of logger for .Net Core. I suggest using of Serilog. It's pretty simple but very flexible and powerful at the same time.
To integrate Serilog into ASP.Net Core application do the following:
Install following NuGet packages:
Serilog.AspNetCore
Serilog.Sinks.Console
Besides Console, Serilog supports many other targets like Rolling File, E-mail, SQL Server, etc. See this list of other Serilog targets.
Configure Serilog on application startup:
Here is a sample:
public class Program
{
public static void Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.Enrich.FromLogContext()
.WriteTo.Console(outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}")
.CreateLogger();
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseSerilog()
.Build();
}
Provided output template adds date and time to logged message:
To expand on CodeFuller's response, here's how you can modify the Serilog Console output formatter purely from configuration:
{
"Serilog": {
"MinimumLevel": {
"Default": "Debug",
"Override": {
"System": "Information",
"Microsoft": "Information"
}
},
"WriteTo:Sublogger": {
"Name": "Logger",
"Args": {
"configureLogger": {
"WriteTo": [
{
"Name": "Console",
"Args": {
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] [{TraceId}] {Message:lj}{NewLine}{Exception}"
}
}
]
}
}
}
}
}
If you take this approach, remove the WriteTo.Console logger method from your startup configuration. This line:
.WriteTo.Console(outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}")
I've also modified the output format template slightly. Either template will work fine.