Kapela.Logs.SqlServerProvider
10.2.0
Prefix Reserved
dotnet add package Kapela.Logs.SqlServerProvider --version 10.2.0
NuGet\Install-Package Kapela.Logs.SqlServerProvider -Version 10.2.0
<PackageReference Include="Kapela.Logs.SqlServerProvider" Version="10.2.0" />
<PackageVersion Include="Kapela.Logs.SqlServerProvider" Version="10.2.0" />
<PackageReference Include="Kapela.Logs.SqlServerProvider" />
paket add Kapela.Logs.SqlServerProvider --version 10.2.0
#r "nuget: Kapela.Logs.SqlServerProvider, 10.2.0"
#:package Kapela.Logs.SqlServerProvider@10.2.0
#addin nuget:?package=Kapela.Logs.SqlServerProvider&version=10.2.0
#tool nuget:?package=Kapela.Logs.SqlServerProvider&version=10.2.0
🗄️ Kapela.Logs.SqlServerProvider
Enregistrez vos logs directement dans Microsoft SQL Server avec création automatique de table et support des colonnes personnalisées.
🧭 Table des matières
- Présentation
- Nouveautés
- Installation
- Démarrage rapide
- Options de configuration
- Création automatique de table
- Gestion manuelle du schéma
- Colonnes personnalisées avec SqlLog
- Scopes
- Lecture des logs
- Configuration appsettings.json
- Exemple complet
🎯 Présentation
Kapela.Logs.SqlServerProvider persiste les logs dans une base de données Microsoft SQL Server. Il offre :
- ✅ Création automatique de la table de logs au démarrage
- ✅ Migration automatique du schéma — tout ajout ou retrait de propriété
[SqlLog]est propagé au prochain démarrage, sans script SQL à écrire - ✅ Mapping automatique des propriétés vers des colonnes SQL via l'attribut
[SqlLog] - ✅ Rétention configurable avec suppression automatique des anciens enregistrements
- ✅ Schéma configurable (par défaut
dbo) - ✅ Écriture bufferisée en arrière-plan pour des performances optimales
📦 Dépend de
Kapela.Logs, installé automatiquement par NuGet — pas besoin de l'ajouter séparément.
🆕 Nouveautés
Cette version introduit la lecture typée des logs via ILogReader, branchée automatiquement lors de l'enregistrement du provider.
Ajouts
- Trois variantes d'
ILogReaderselon le typage des propriétés étendues (ILogReader,ILogReader<TLogProps>,ILogReader<TLogProps, TScopeProps>). - DTO
LogEntryetScopeEntry(et leurs variantes génériques) — retournés par le reader, colonnes standards + propriétés étendues typées + scope parent. - Requêtes fluentes
LogQuery/ScopeQuery—Take(n),OrderAscending()/OrderDescending(),ForScope(Guid),WithoutScope(). - Pagination SQL Server native via
TOP (n); rattachement des scopes aux logs en une seule requête groupée (pas de N+1).
Enregistrement automatique
- Chaque surcharge
UseSqlServerProviderenregistre désormais la variante d'ILogReadercorrespondante dans l'injection de dépendances.
Note
- Renommage du nom de
ScopeTableNamepar défaut :"LogsOperation"→"LogsOperations".
📖 Détail d'utilisation dans la section Lecture des logs plus bas.
📥 Installation
.NET CLI
dotnet add package Kapela.Logs.SqlServerProvider
Package Manager Console
Install-Package Kapela.Logs.SqlServerProvider
🚀 Démarrage rapide
using Kapela.Logs;
using Kapela.Logs.SqlServerProvider;
builder.UseKapelaLogs(logs =>
{
logs.UseSqlServerProvider(
"Server=myServer;Database=myDB;Trusted_Connection=True;",
new SqlServerLoggerOptions
{
TableName = "AppLogs",
AutoCreateTable = true,
NbDayRetention = 90
}
);
});
⚙️ Options de configuration
| Propriété | Type | Description | Défaut |
|---|---|---|---|
ConnectionString |
string |
Lecture seule — définie via le paramètre de UseSqlServerProvider() |
— |
SqlSchema |
string |
Schéma de la table | "dbo" |
TableName |
string |
Nom de la table de logs | "Logs" |
AutoCreateTable |
bool |
Crée le schéma (SqlSchema) puis la table s'ils n'existent pas |
false |
AutoMigrate |
bool |
Compare le schéma de la table avec le modèle et applique les différences (colonnes ajoutées ou supprimées). Nécessite AutoCreateTable = true. |
false |
AutoMigrateAllowDrop |
bool |
Autorise la suppression des colonnes obsolètes. Si false, les colonnes absentes du modèle sont rendues nullable plutôt que supprimées. Nécessite AutoMigrate = true. |
false |
EnableScopes |
bool |
Active la gestion des scopes. Crée une table LogsOperations et ajoute une colonne OperationId dans Logs. |
false |
ScopeTableName |
string |
Nom de la table des opérations (scopes). | "LogsOperations" |
NbDayRetention |
uint |
Jours de conservation (0 = illimité) |
0 |
Timeout |
uint |
Délai d'expiration des commandes SQL en secondes (0 = pas de limite) |
0 |
GlobalLogLevel |
LogLevel? |
Niveau minimal pour ce provider | Information |
🏗️ Création automatique de table
C'est le mode recommandé : avec AutoCreateTable = true (combiné ou non à AutoMigrate = true), le provider crée au premier démarrage le schéma SqlSchema (s'il n'existe pas) puis la table, et aligne ensuite ses colonnes sur votre modèle .NET à chaque démarrage suivant. Aucune DDL à rédiger, aucune migration à synchroniser à la main.
ℹ️ Le schéma n'est jamais supprimé. Si
SqlSchemaest vide, aucune qualification par schéma n'est appliquée.
CREATE TABLE [dbo].[AppLogs] (
[Id] [int] IDENTITY(1,1) NOT NULL,
[Date] [datetime] NOT NULL,
[Level] [nvarchar](20) NOT NULL,
[LevelId] [int] NOT NULL,
[Source] [nvarchar](100) NOT NULL,
[Message] [nvarchar](MAX) NOT NULL,
[Exception] [nvarchar](MAX) NULL
)
📌 Besoin de garder la main sur le schéma (migrations EF Core, Flyway, Liquibase, scripts DBA) ? Voir Gestion manuelle du schéma juste en dessous.
🛠️ Gestion manuelle du schéma
Les options d'automatisation (AutoCreateTable, AutoMigrate, AutoMigrateAllowDrop) sont désactivées par défaut. Sans action explicite, le provider ne crée, n'altère ni ne supprime aucune table ni colonne — il se contente d'insérer les logs dans les tables existantes.
Ce mode permet d'intégrer le provider dans un projet dont le schéma est déjà piloté par un outil de migration externe. Il est fonctionnel mais moins confortable : c'est à vous de garantir que la base reste alignée sur le modèle .NET.
Dans ce mode, vous êtes responsable de :
- créer la table de logs avec les colonnes standards (
Id,Date,Level,LevelId,Source,Message,Exception) et les colonnes issues de votreILogProperties; - si les scopes sont activés, créer la table
LogsOperations(PKIdGUID, colonnesName,StartDate,EndDatenullable, plus les colonnes issues de votreILogScopeProperties) et ajouter une colonneOperationIdnullable dans la table de logs ; - maintenir la cohérence du schéma lors des évolutions de votre modèle — tout nouveau
[SqlLog]ou toute colonne retirée doit être reflété en base.
💡 Recommandation — pour la grande majorité des déploiements, laisser le provider gérer la création et la migration supprime une classe entière de bugs (oubli d'une colonne après ajout d'un
[SqlLog], désalignement entre prod et dev). Privilégiez la gestion manuelle seulement si votre environnement l'impose (politique DBA, pipeline de migration déjà en place).
🏷️ Colonnes personnalisées avec [SqlLog]
L'attribut [SqlLog] mappe des propriétés .NET vers des colonnes SQL. Il s'applique aussi bien aux logs (classes implémentant ILogProperties) qu'aux scopes (classes implémentant ILogScopeProperties — voir section Scopes plus bas).
Enrichissez vos logs avec des données métier en implémentant ILogProperties :
using Kapela.Logs;
public class AppLogContext : ILogProperties
{
[SqlLog(Name = "UserId", MaxLength = 50)]
public string? UserId { get; set; }
[SqlLog(MaxLength = 200)]
public string? RequestPath { get; set; }
[SqlLog]
public int? StatusCode { get; set; }
[SqlLog(Name = "CorrelationId", MaxLength = 36)]
public string? TraceId { get; set; }
}
Paramètres de [SqlLog]
| Paramètre | Type | Description |
|---|---|---|
Name |
string |
Nom de la colonne en base (défaut : nom de la propriété) |
MaxLength |
uint |
Taille maximale pour les colonnes nvarchar |
Enregistrement avec le contexte personnalisé
builder.UseKapelaLogs(logs =>
{
logs.UseSqlServerProvider<AppLogContext>(
connectionString,
new SqlServerLoggerOptions { AutoCreateTable = true }
);
});
🔗 Scopes
Les scopes permettent de regrouper plusieurs logs sous une opération logique commune. Chaque log émis dans le scope est lié à l'opération via une colonne OperationId dans la table de logs ; l'opération elle-même est tracée dans une table dédiée (LogsOperations).
Activation
builder.UseKapelaLogs(logs =>
{
logs.UseSqlServerProvider(
connectionString,
new SqlServerLoggerOptions
{
AutoCreateTable = true,
AutoMigrate = true, // requis si la table Logs existe déjà
EnableScopes = true
}
);
});
⚠️ Si la table
Logsa été créée sansEnableScopes, la colonneOperationIdest absente.AutoMigrate = trueest nécessaire pour qu'elle soit ajoutée automatiquement au démarrage. Sans cela, l'émission d'un log dans un scope provoquera une erreur SQL.
Propriétés étendues sur l'opération (ILogScopeProperties)
Pour ajouter des colonnes personnalisées à la table LogsOperations, créez une classe implémentant ILogScopeProperties :
public class MyScopeProps : ILogScopeProperties
{
[SqlLog(Name = "CommandeId")]
public Guid? CommandeId { get; set; }
[SqlLog(MaxLength = 100)]
public string? Client { get; set; }
}
Enregistrez les deux types au niveau du provider :
logs.UseSqlServerProvider<AppLogContext, MyScopeProps>(connectionString, options);
Utilisation
var scope = new LogScope("TraiterCommande", new MyScopeProps
{
CommandeId = commandeId,
Client = "dupont"
});
using (logger.BeginScope(scope))
{
logger.LogInformation("Début du traitement");
logger.LogWarning("Stock faible");
}
// À la sortie du using : EndDate est renseignée dans LogsOperations
Tables générées
LogsOperations
| Colonne | Description |
|---|---|
Id (GUID) |
Clé primaire |
Name |
Nom de l'opération |
StartDate |
Date de début |
EndDate (nullable) |
Date de fin, renseignée à la fermeture du scope |
| (colonnes étendues) | Issues de ILogScopeProperties |
Logs — colonne ajoutée :
| Colonne | Description |
|---|---|
OperationId (GUID, nullable) |
Référence vers LogsOperations |
📖 Lecture des logs
Chaque surcharge de UseSqlServerProvider() enregistre aussi un ILogReader adapté dans l'injection de dépendances. Résolvez-le par injection pour interroger la base sans réécrire de SQL.
Variantes enregistrées
| Surcharge utilisée | Lecteur enregistré |
|---|---|
UseSqlServerProvider(cs, options) |
ILogReader |
UseSqlServerProvider<TLogProps>(cs, options) |
ILogReader<TLogProps> |
UseSqlServerProvider<TLogProps, TScopeProps>(cs, options) |
ILogReader<TLogProps, TScopeProps> |
Requête fluente — LogQuery
| Méthode | Rôle | Défaut |
|---|---|---|
Take(uint) |
Nombre maximum de logs | 100 |
OrderAscending() / OrderDescending() |
Tri par Date |
Descendant |
ForScope(Guid) |
Restreint aux logs d'un scope donné (requiert EnableScopes = true) |
— |
WithoutScope() |
Restreint aux logs orphelins non rattachés à un scope (requiert EnableScopes = true) |
— |
Requête fluente — ScopeQuery
| Méthode | Rôle | Défaut |
|---|---|---|
Take(uint) |
Nombre maximum de scopes | 100 |
OrderAscending() / OrderDescending() |
Tri par StartDate |
Descendant |
ForScope(Guid) |
Restreint à un scope précis (0 ou 1 résultat) | — |
💡
GetScopesAsync()retourne[]siEnableScopes = false. Même comportement pourGetLogsAsync(q => q.ForScope(...))etGetLogsAsync(q => q.WithoutScope())quand les scopes sont désactivés.
Exemple
public class LogsPage(ILogReader<AppLogContext, MyScopeProps> reader)
{
public async Task<IReadOnlyList<LogEntry<AppLogContext, MyScopeProps>>> LoadAsync(CancellationToken ct)
{
return await reader.GetLogsAsync(q => q.Take(50).OrderDescending(), ct);
}
}
Chaque LogEntry<TLogProps, TScopeProps> expose :
- les colonnes standards (
Id,Date,LogLevel,Source,Message,Exception), - les propriétés étendues fortement typées via
ExtendedProperties(instance deTLogProps), - le scope parent typé via
Scope(instance deScopeEntry<TScopeProps>?), s'il existe.
⚙️ Pagination : SQL Server utilise
TOP (n); les scopes sont rattachés aux logs en une seule requête groupée (pas de N+1).
⚙️ Configuration appsettings.json
{
"Logging": {
"SqlServer": {
"SqlSchema": "dbo",
"TableName": "AppLogs",
"AutoCreateTable": true,
"NbDayRetention": 90,
"Timeout": 30,
"GlobalLogLevel": "Information",
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning"
}
}
},
"ConnectionStrings": {
"Logs": "<votre chaîne de connexion>"
}
}
🔐 ConnectionString : passez-la toujours via
builder.Configuration.GetConnectionString("Logs")(sectionConnectionStringsd'appsettings.json) plutôt que dansLogging:SqlServer. Ne stockez jamais une chaîne de connexion en clair — si vous utilisezKapela.Security.Encryption, préférezEncryptionHelper.GetConnectionString(builder.Configuration, "Logs")qui gère automatiquement le déchiffrement.
💡 Exemple complet
// Propriétés étendues
public class AppLogContext : ILogProperties
{
[SqlLog(MaxLength = 50)]
public string? UserId { get; set; }
[SqlLog(MaxLength = 20)]
public string? AppEnvironment { get; set; }
}
// Program.cs
builder.UseKapelaLogs(logs =>
{
logs.UseSqlServerProvider<AppLogContext>(
builder.Configuration.GetConnectionString("Logs")!, // sans chiffrement
// EncryptionHelper.GetConnectionString(builder.Configuration, "Logs"), // avec Kapela.Security.Encryption
new SqlServerLoggerOptions
{
SqlSchema = "logs",
TableName = "ApplicationLogs",
AutoCreateTable = true,
NbDayRetention = 365,
GlobalLogLevel = LogLevel.Information,
LogLevel =
{
["Microsoft.AspNetCore"] = LogLevel.Warning
}
}
);
});
// MyService.cs
public class MyService(ILogger<MyService> logger)
{
public void ProcessRequest(string userId, string path)
{
logger.LogInformation("Requête reçue", new AppLogContext
{
UserId = userId,
AppEnvironment = "Production"
});
logger.LogError("Erreur lors du traitement", new AppLogContext
{
UserId = userId,
AppEnvironment = "Production"
});
}
}
📄 Licence MIT — © Kapela 2024-2026
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Kapela.Logs (>= 10.2.0)
- Microsoft.Data.SqlClient (>= 7.0.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.