ZNetCS.AspNetCore.Logging.EntityFrameworkCore
6.0.0
dotnet add package ZNetCS.AspNetCore.Logging.EntityFrameworkCore --version 6.0.0
NuGet\Install-Package ZNetCS.AspNetCore.Logging.EntityFrameworkCore -Version 6.0.0
<PackageReference Include="ZNetCS.AspNetCore.Logging.EntityFrameworkCore" Version="6.0.0" />
paket add ZNetCS.AspNetCore.Logging.EntityFrameworkCore --version 6.0.0
#r "nuget: ZNetCS.AspNetCore.Logging.EntityFrameworkCore, 6.0.0"
// Install ZNetCS.AspNetCore.Logging.EntityFrameworkCore as a Cake Addin #addin nuget:?package=ZNetCS.AspNetCore.Logging.EntityFrameworkCore&version=6.0.0 // Install ZNetCS.AspNetCore.Logging.EntityFrameworkCore as a Cake Tool #tool nuget:?package=ZNetCS.AspNetCore.Logging.EntityFrameworkCore&version=6.0.0
ZNetCS.AspNetCore.Logging.EntityFrameworkCore
This is Entity Framework Core logger and logger provider. A small package to allow store logs in any data store using Entity Framework Core. It was prepared to use in ASP NET Core application, but it does not contain any references that prevents to use it in plain .NET Core application.
As from version 2.0.2 there is silent error handling on logger SaveChanges(). To avoid Db error having impact on application.
Installing
Install using the ZNetCS.AspNetCore.Logging.EntityFrameworkCore NuGet package
PM> Install-Package ZNetCS.AspNetCore.Logging.EntityFrameworkCore
Usage
When you install the package, it should be added to your .csproj
. Alternatively, you can add it directly by adding:
<ItemGroup>
<PackageReference Include="ZNetCS.AspNetCore.Logging.EntityFrameworkCore" Version="6.0.0" />
</ItemGroup>
.NET 6
In order to use the IP filtering middleware, you must configure the services in the Program.cs
file.
// Add services to the container.
builder.Logging.AddEntityFramework<MyDbContext>();
.NET 5 and Below
public static void Main(string[] args)
{
var webHost = new WebHostBuilder()
// other code ommited to focus on logging settings
.ConfigureLogging((hostingContext, logging) =>
{
// other log providers
// ...
//
logging.AddEntityFramework<MyDbContext>();
})
.UseStartup<Startup>()
.Build();
webHost.Run();
}
Important Notes
In most case scenario you would not like add all logs from application to database. A lot of of them is jut debug/trace ones. In that case is better use filter before
add Logger
. This will also prevent some StackOverflowException
when using this logger to log EntityFrameworkCore
logs.
.NET 6
builder.Logging..AddFilter<EntityFrameworkLoggerProvider<MyDbContent>>("Microsoft", LogLevel.None);
builder.Logging..AddFilter<EntityFrameworkLoggerProvider<MyDbContent>>("System", LogLevel.None);
builder.Logging..AddEntityFramework<MyDbContext>();
.NET 5 and Below
public static void Main(string[] args)
{
var webHost = new WebHostBuilder()
// other code ommited to focus on logging settings
.ConfigureLogging((hostingContext, logging) =>
{
// other log providers
// ...
//
// because setting up filter inside code requires exact provider class, and EntityFrameworkLoggerProvider is generic class with multiple overrides
// filters needs to applied properly to chosen provider
logging.AddFilter<EntityFrameworkLoggerProvider<MyDbContent>>("Microsoft", LogLevel.None);
logging.AddFilter<EntityFrameworkLoggerProvider<MyDbContent>>("System", LogLevel.None);
logging.AddEntityFramework<MyDbContext>();
})
.UseStartup<Startup>()
.Build();
webHost.Run();
}
It is also possible to setting filters inside appsettings.json
file. This provider is using EntityFramework
alias. This way is recommended because there is no need to
care about proper provider definition.
{
"Logging": {
"EntityFramework": {
"LogLevel": {
"Microsoft": "None",
"System": "None"
}
}
}
}
public static void Main(string[] args)
{
var webHost = new WebHostBuilder()
// other code ommited to focus on logging settings
.ConfigureLogging((hostingContext, logging) =>
{
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
// other log providers
// ...
//
logging.AddEntityFramework<MyDbContext>();
})
.UseStartup<Startup>()
.Build();
webHost.Run();
}
Then you need to setup your context to have access to log table e.g.
using ZNetCS.AspNetCore.Logging.EntityFrameworkCore;
public class MyDbContext : DbContext
{
public MyDbContext(DbContextOptions options) : base(options)
{
}
public DbSet<Log> Logs { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// build default model.
LogModelBuilderHelper.Build(modelBuilder.Entity<Log>());
// real relation database can map table:
modelBuilder.Entity<Log>().ToTable("Log");
}
}
There is also possibility to extend base Log
class.
public class ExtendedLog : Log
{
public ExtendedLog(IHttpContextAccessor accessor)
{
string browser = accessor.HttpContext.Request.Headers["User-Agent"];
if (!string.IsNullOrEmpty(browser) && (browser.Length > 255))
{
browser = browser.Substring(0, 255);
}
this.Browser = browser;
this.Host = accessor.HttpContext.Connection?.RemoteIpAddress?.ToString();
this.User = accessor.HttpContext.User?.Identity?.Name;
this.Path = accessor.HttpContext.Request.Path;
}
protected ExtendedLog()
{
}
public string Browser { get; set; }
public string Host { get; set; }
public string Path { get; set; }
public string User { get; set; }
}
Change MyDbContext
to use new extended log model
public DbSet<ExtendedLog> Logs => this.Set<ExtendedLog>;
You can extend ModelBuilder
as well:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// build default model.
LogModelBuilderHelper.Build(modelBuilder.Entity<ExtendedLog>());
// real relation database can map table:
modelBuilder.Entity<ExtendedLog>().ToTable("Log");
modelBuilder.Entity<ExtendedLog>().Property(r => r.Id).ValueGeneratedOnAdd();
modelBuilder.Entity<ExtendedLog>().HasIndex(r => r.TimeStamp).HasName("IX_Log_TimeStamp");
modelBuilder.Entity<ExtendedLog>().HasIndex(r => r.EventId).HasName("IX_Log_EventId");
modelBuilder.Entity<ExtendedLog>().HasIndex(r => r.Level).HasName("IX_Log_Level");
modelBuilder.Entity<ExtendedLog>().Property(u => u.Name).HasMaxLength(255);
modelBuilder.Entity<ExtendedLog>().Property(u => u.Browser).HasMaxLength(255);
modelBuilder.Entity<ExtendedLog>().Property(u => u.User).HasMaxLength(255);
modelBuilder.Entity<ExtendedLog>().Property(u => u.Host).HasMaxLength(255);
modelBuilder.Entity<ExtendedLog>().Property(u => u.Path).HasMaxLength(255);
}
To use IHttpContextAccessor
there is need to register it inside ConfigureServices
call of Startup
:
public void ConfigureServices(IServiceCollection services)
{
// requires for http context access.
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
}
Add extended log registration
public static void Main(string[] args)
{
var webHost = new WebHostBuilder()
// other code ommited to focus on logging settings
.ConfigureLogging((hostingContext, logging) =>
{
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
// other log providers
// ...
//
logging.AddEntityFramework<MyDbContext, ExtendedLog>();
})
.UseStartup<Startup>()
.Build();
webHost.Run();
}
There is also possibility to create new log model using custom creator method. This can be done by providing options during configuration.
public static void Main(string[] args)
{
var webHost = new WebHostBuilder()
// other code ommited to focus on logging settings
.ConfigureLogging((hostingContext, logging) =>
{
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
// other log providers
// ...
//
logging.AddEntityFramework<MyDbContext>(
opts =>
{
opts.Creator = (logLevel, eventId, name, message) => new Log
{
TimeStamp = DateTimeOffset.Now,
Level = logLevel,
EventId = eventId,
Name = "This is my custom log",
Message = message
};
});
})
.UseStartup<Startup>()
.Build();
webHost.Run();
}
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 is compatible. net5.0-windows was computed. net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp3.1 is compatible. |
-
.NETCoreApp 3.1
- Microsoft.EntityFrameworkCore (>= 3.1.22)
-
net5.0
- Microsoft.EntityFrameworkCore (>= 5.0.13)
-
net6.0
- Microsoft.EntityFrameworkCore (>= 6.0.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Breaking Change: Drop support for netstandard and .net framework. Code refactoring. Dependency update. Nullable enable.