NET 5.0 - serilog-sinks-file not creating logs - serilog

Since I updated my code to .NET 5.0 and used a newer version of serilog, I cannot get any rolling file anymore
I tried debugging serilog , it creates a debug file but nothing is in there
private static void CreateLogger()
{
// Init Serilog configuration
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.logs.json")
.Build();
Log.Logger = new Serilog.LoggerConfiguration().ReadFrom.Configuration(configuration)
.Enrich.WithProperty("Application", GetAssemblyProductName())
.CreateLogger();
var file = File.CreateText(AppDomain.CurrentDomain.BaseDirectory + #"serilog.txt");
Serilog.Debugging.SelfLog.Enable(TextWriter.Synchronized(file));
Serilog.Debugging.SelfLog.Enable(msg => Debug.WriteLine(msg));
Serilog.Debugging.SelfLog.Enable(Console.Error);
}
here is my appsetings.log.json
{
"Serilog": {
"Using": [
"Serilog.Sinks.ApplicationInsights"
],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Warning",
"System.Net.Http.HttpClient": "Warning"
}
},
"WriteTo": [
{
"Name": "Async",
"Args": {
"configure": [
{
"Name": "File",
"Args": {
"pathFormat": "logs.txt",
"formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact",
"outputTemplate": "({SourceContext}) {Message}{NewLine}{Exception}",
"rollingInterval": "Day",
"fileSizeLimitBytes": 50000000,
"rollOnFileSizeLimit": true,
"retainedFileCountLimit": 15,
"buffered": true
}
},
{
"Name": "ApplicationInsights",
"Args": {
"restrictedToMinimumLevel": "Information",
"outputTemplate": "({SourceContext}) ({Application}/{MachineName}/{ThreadId}) {Message}{NewLine}{Exception}",
"telemetryConverter": "Serilog.Sinks.ApplicationInsights.Sinks.ApplicationInsights.TelemetryConverters.TraceTelemetryConverter, Serilog.Sinks.ApplicationInsights"
}
}
]
}
}
],
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
"Properties": {
"Application": "myapp"
}
}
}
am I missing something ?
thanks for helping me on this

Please someone correct me if this is wrong but I assumed you need to list the sinks you wanted to run in the Using section - therefore adding the File sink to your appsettings should fix this - as per below:
"Serilog": {
"Using": [
"Serilog.Sinks.ApplicationInsights","Serilog.Sinks.File"
],

Related

Serilog - Not logging to SQL

Hoping someone can provide some information on how to configure Serilog to write to MSSql in an ASP.Net Core DotNet 6 application, I have followed the configurations seen on the Web but nothing seems to work. Serilog logs okay to the console and to file but not to the database.
I have included all my configuration code below:
builder.Host.UseSerilog((ctx, lc) =>
lc.ReadFrom.Configuration(ctx.Configuration));
app.UseSerilogRequestLogging();
Appsetting.jason config:
"Serilog": {
"Using": [ "Serilog.Sinks.Console", "Serilog.sinks.File", "Serilog.Sinks.MSSqlServer" ],
"Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId", "WithThreadId" ],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"WriteTo": [
{
"Name": "MSSqlServer",
"Args": {
"connectionString": "RevIntraConnection",
"tableName": "DBLogs",
"autoCreateSqlTable": false
}
},
{
"Name": "File",
"Args": {
"path": "./Logs/Log-.txt",
"rollingInterval": "Day"
}
},
{ "Name": "Console" }
]
},
Hopefully someone can provide some insight in how to get the correct configuration to make logging to SQL work
Regards
Peter

Serilog configuration for microsoft still overrides logging information level logs

I have the following settings defined, but I am still getting all put/get requests logged to my api, even though these are supposed to be "Microsoft".
Can anyone share advice?
"Serilog": {
"Using": [ "Serilog.Sinks.Console" ],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"WriteTo": [
{ "Name": "Console" },
{
"Name": "Seq",
"Args": { "serverUrl": "http://logserver:5341" }
},
{
"Name": "File",
"Args": {
"path": "c:\\temp\\events.api.txt",
"rollingInterval": "Day"
}
}
],
"Properties": {
"Application": "Events API"
}
},
Example of a log:
[13:55:10 INF] Source:[::1] Request: PUT https localhost:44320/api
{json request object} Responded with [200] in 2ms
return Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
webBuilder.UseSerilog((hostingContext, loggerConfiguration) => loggerConfiguration
.ReadFrom.Configuration(hostingContext.Configuration)
.Enrich.FromLogContext());
});

Using RestrictedToMinimumLevel to Override the Default Minimum Level in Serilog

I have configured Serilog to have a default MinimumLevel of Verbose.
But I want to confine the logging to SQL Server to Warning (and up).
My config (in JSON) looks like this:
{
"Serilog": {
"Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File", "Serilog.Sinks.MSSqlServer", "My.Framework.AspNet" ],
"Enrich": [ "FromLogContext", "WithEventType" ],
"MinimumLevel": {
"Default": "Verbose"
},
"WriteTo": [
{
"Name": "MSSqlServer",
"restrictedToMinimumLevel": "Warning",
"Args": {
"connectionString": "Server=yada yada yada ;MultipleActiveResultSets=True",
"tableName": "ErrorLogs",
"autoCreateSqlTable": false,
"columnOptionsSection": {
"disableTriggers": true,
"clusteredColumnstoreIndex": false,
"primaryKeyColumnName": "Id",
"addStandardColumns": [ "LogEvent" ],
"removeStandardColumns": [ "Properties" ],
"additionalColumns": [
{
"ColumnName": "EventType",
"DataType": "bigint",
"AllowNull": true
}
],
"id": {
"columnName": "Id",
"nonClusteredIndex": true
},
"eventType": {
"columnName": "EventType"
},
"message": {
"columnName": "Message"
},
"messageTemplate": {
"columnName": "MessageTemplate"
},
"level": {
"columnName": "Level",
"storeAsEnum": false
},
"timeStamp": {
"columnName": "TimeStamp",
"convertToUtc": true
},
"exception": {
"columnName": "Exception"
},
"logEvent": {
"columnName": "LogEvent"
}
}
}
}
],
"Properties": {
"Application": "App API"
}
}
}
Upon inspecting my logs, I'm seeing everything from Verbose up.
Is there something I'm doing wrong with the restrictedToMinimumLevel property?
I also tried placing it inside the Args property, with no luck.
Cheers
I haven't tried it but upon this GitHub issue I think restrictedToMinimumLevel should be in Args. So change your WriteTo configuration like this:
"WriteTo": [
{
"Name": "MSSqlServer",
"Args": {
"restrictedToMinimumLevel": "Warning",
"connectionString": "Server=yada yada yada ;MultipleActiveResultSets=True",
"tableName": "ErrorLogs",
"autoCreateSqlTable": false,
"columnOptionsSection": {
"disableTriggers": true,
"clusteredColumnstoreIndex": false,
"primaryKeyColumnName": "Id",
"addStandardColumns": [ "LogEvent" ],
"removeStandardColumns": [ "Properties" ],
"additionalColumns": [
{
"ColumnName": "EventType",
"DataType": "bigint",
"AllowNull": true
}
],
"id": {
"columnName": "Id",
"nonClusteredIndex": true
},
"eventType": {
"columnName": "EventType"
},
"message": {
"columnName": "Message"
},
"messageTemplate": {
"columnName": "MessageTemplate"
},
"level": {
"columnName": "Level",
"storeAsEnum": false
},
"timeStamp": {
"columnName": "TimeStamp",
"convertToUtc": true
},
"exception": {
"columnName": "Exception"
},
"logEvent": {
"columnName": "LogEvent"
}
}
}
}
]
For the restrictedToMinimumLevel to work via configuration through appSettings.json, the restrictedToMinimumLevel must be inside the Args section as it's described in the documentation. There's nothing unique about the MsSQLServer sink that would require the configuration to be any different.
As you can see, only events with log level >= Warning are stored in the SQL Server table:
Program.cs
using System;
using System.IO;
using Microsoft.Extensions.Configuration;
using Serilog;
using Serilog.Debugging;
namespace ReproSerilogSO66019586
{
class Program
{
static void Main(string[] args)
{
SelfLog.Enable(msg => Console.WriteLine("ERROR: {0}", msg));
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build();
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.WriteTo.Console()
.CreateLogger();
Log.Verbose("This is Verbose!");
Log.Debug("This is Debug!");
Log.Information("This is Information!");
Log.Warning("This is Warning!");
Log.Error("This is Error!");
Log.Fatal("This is Fatal!");
Log.CloseAndFlush();
Console.ReadLine();
}
}
}
appSettings.json
{
"Serilog": {
"Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File", "Serilog.Sinks.MSSqlServer" ],
"Enrich": [ "FromLogContext" ],
"MinimumLevel": {
"Default": "Verbose"
},
"WriteTo": [
{
"Name": "MSSqlServer",
"Args": {
"restrictedToMinimumLevel": "Warning",
"connectionString": "Server=(local);MultipleActiveResultSets=True",
"tableName": "ErrorLogs",
"autoCreateSqlTable": true,
"columnOptionsSection": {
"disableTriggers": true,
"clusteredColumnstoreIndex": false,
"primaryKeyColumnName": "Id",
"addStandardColumns": [ "LogEvent" ],
"removeStandardColumns": [ "Properties" ],
"additionalColumns": [
{
"ColumnName": "EventType",
"DataType": "bigint",
"AllowNull": true
}
],
"id": {
"columnName": "Id",
"nonClusteredIndex": true
},
"message": {
"columnName": "Message"
},
"messageTemplate": {
"columnName": "MessageTemplate"
},
"level": {
"columnName": "Level",
"storeAsEnum": false
},
"timeStamp": {
"columnName": "TimeStamp",
"convertToUtc": true
},
"exception": {
"columnName": "Exception"
},
"logEvent": {
"columnName": "LogEvent"
}
}
}
}
],
"Properties": {
"Application": "App API"
}
}
}

How to configure Serilog.Exceptions.SqlServer in appsettings.json

I'm using appsettings.json to configure Serilog. I added Serilog.Exceptions, which works like a charm.
"Serilog": {
"Using": [ "Serilog.Sinks.Console", "Serilog.Settings.Configuration", "Serilog.Exceptions" ],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"WriteTo": [
{ "Name": "Console" },
{
"Name": "File",
"Args": {
"path": "%TEMP%\\Logs\\serilog-configuration-sample.txt",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception} {Properties:j}",
"rollingInterval": "Day"
}
}
],
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId", "WithExceptionDetails" ]
}
But since I'm using Sql Server and EF Core, the documentation says I also have to configure Serilog.Exceptions.SqlServer and Serilog.Exceptions.EntityFrameworkCore.
According to this documentation this has to be added to the enrichter. In C# code this would be:
.Enrich.WithExceptionDetails(new DestructuringOptionsBuilder()
.WithDefaultDestructurers()
.WithDestructurers(new[] { new SqlExceptionDestructurer() }))
I can't figure out how to do that in appsettings.json. Can anyone help me with that?
This isn't possible at the moment, although the author is open for a PR if someone implements it.
See this issue, this discussion and this related question.

Persisting EventType with Serilog

I'm having trouble getting the EventType feature working in Serilog, as blogged about here.
I am using the following Nuget packages:
Serilog 2.8
Serilog.Settings.Configuration 3.0.1
Serilog.Sinks.File 4.0.0
Serilog.Sinks.MSSqlServer 5.1.2
First up, I created an EventTypeEnricher:
public class EventTypeEnricher : ILogEventEnricher
{
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
{
var crypto = new SimpleCrypto.PBKDF2();
var hash = crypto.Compute(logEvent.MessageTemplate.Text);
var numericHash = BitConverter.ToUInt32(Encoding.UTF8.GetBytes(hash), 0);
var eventId = propertyFactory.CreateProperty("EventType", numericHash);
logEvent.AddPropertyIfAbsent(eventId);
}
}
This seems to work (more on that later, but at the end of that method, a property is added with an EventType value in the EventId variable can be observed while debugging).
I created an extension method which adds this enricher:
public static LoggerConfiguration WithEventType(this LoggerEnrichmentConfiguration enrichmentConfiguration)
{
if (enrichmentConfiguration == null) throw new ArgumentNullException(nameof(enrichmentConfiguration));
return enrichmentConfiguration.With<EventTypeEnricher>();
}
I then use that when I configure the Logger:
Log.Logger = new LoggerConfiguration()
.Enrich.WithEventType()
.ReadFrom.Configuration(configuration)
.CreateLogger();
I go to write the error like this:
logger.Write(LogEventLevel.Error,
contextFeature.Error,
MessageTemplates.LogEntryDetailMessageTemplate,
new LogEntryDetail
{
Exception = contextFeature.Error,
Message = "Bad Stuff",
Timestamp = DateTime.UtcNow,
MessageTemplate = MessageTemplates.LogEntryDetailMessageTemplate,
Severity = LogEventLevel.Error
});
My Serilog appsettings section is as follows:
"Serilog": {
"Using": [ "Serilog.Sinks.File", "Serilog.Sinks.MSSqlServer", "MyAssembly" ],
"Enrich": [ "EventTypeEnricher" ],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "Logs//Errorlog.log",
"fileSizeLimitBytes": 1073741824,
"retainedFileCountLimit": 30,
"rollingInterval": "Day",
"rollOnFileSizeLimit": true
},
"restrictedToMinimumLevel": "Verbose"
},
{
"Name": "MSSqlServer",
"Args": {
"connectionString": "Data Source=(local);Initial Catalog=ADb;User Id=Serilog;Password=securepwd;",
"tableName": "ErrorLogs",
"autoCreateSqlTable": false,
"period": 30,
"columnOptionsSection": {
"disableTriggers": true,
"clusteredColumnstoreIndex": false,
"primaryKeyColumnName": "Id",
"addStandardColumns": [ "LogEvent" ],
"removeStandardColumns": [ "Properties" ],
"additionalColumns": [
{
"ColumnName": "EventType",
"DataType": "int",
"AllowNull": true
}
],
"id": { "nonClusteredIndex": true },
"level": {
"columnName": "Level",
"storeAsEnum": false
},
"timeStamp": {
"columnName": "Timestamp",
"convertToUtc": true
},
"logEvent": {
"excludeAdditionalProperties": true,
"excludeStandardColumns": true
},
"message": { "columnName": "Message" },
"exception": { "columnName": "Exception" },
"messageTemplate": { "columnName": "MessageTemplate" }
}
},
"restrictedToMinimumLevel": "Verbose"
}
]
}
My database table looks like this:
CREATE TABLE [dbo].[ErrorLogs](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[EventType] [int] NULL,
[Message] [nvarchar](max) NULL,
[MessageTemplate] [nvarchar](max) NULL,
[Level] [nvarchar](128) NULL,
[TimeStamp] [datetime] NOT NULL,
[Exception] [nvarchar](max) NULL,
[Properties] [nvarchar](max) NULL,
[LogEvent] [nvarchar](max) NULL,
CONSTRAINT [PK_ErrorLogs] PRIMARY KEY NONCLUSTERED
The EventType column in the database is always null, despite the code in the custom enricher running.
It is not written to the file sink either.
Can anyone see what I am doing wrong or missing?
Cheers
Updating to Serilog.Sinks.MSSqlServer version 5.1.3 fixed the issue as current stable version 5.1.2 not reading all columnOptionsSection section
Install-Package Serilog.Sinks.MSSqlServer -Version 5.1.3
And below updated configuration will fix your issue as you miss table mapping for EventType field
"Serilog": {
"Using": [ "Serilog.Sinks.File", "Serilog.Sinks.MSSqlServer", "MyAssembly" ],
"Enrich": [ "WithEventType" ],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "Logs//Errorlog.log",
"fileSizeLimitBytes": 1073741824,
"retainedFileCountLimit": 30,
"rollingInterval": "Day",
"rollOnFileSizeLimit": true
},
"restrictedToMinimumLevel": "Verbose"
},
{
"Name": "MSSqlServer",
"Args": {
"connectionString": "Data Source=(local);Initial Catalog=ADb;User Id=Serilog;Password=securepwd;",
"tableName": "ErrorLogs",
"autoCreateSqlTable": false,
"columnOptionsSection": {
"disableTriggers": true,
"clusteredColumnstoreIndex": false,
"primaryKeyColumnName": "Id",
"addStandardColumns": [ "LogEvent" ],
"additionalColumns": [
{
"ColumnName": "EventType",
"DataType": "int",
"AllowNull": true
}
],
"id": {
"columnName": "Id",
"nonClusteredIndex": true
},
"eventType": {
"columnName": "EventType"
},
"message": {
"columnName": "Message"
},
"messageTemplate": {
"columnName": "MessageTemplate"
},
"level": {
"columnName": "Level",
"storeAsEnum": false
},
"timeStamp": {
"columnName": "TimeStamp",
"convertToUtc": true
},
"exception": {
"columnName": "Exception"
},
"properties": {
"columnName": "Properties"
},
"logEvent": {
"columnName": "LogEvent"
}
}
}
}
]
}
And Logger configuration as below
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.CreateLogger();

Resources