web-dev-qa-db-fra.com

Serilog.Sinks.MSSqlServer ne remplit pas les colonnes personnalisées

J'ai regardé autour de moi, mais je n'ai pas pu trouver de solution de travail, et puisque tous les exemples se ressemblent, je suppose que ce doit être moi qui oublie quelque chose d'évident. Notez également qu'il s'agit de mon premier véritable projet utilisant NET Core et Serilog.

Le problème

J'essaie de connecter (à l'aide de serilog) certaines propriétés personnalisées dans leurs propres colonnes dans la base de données, comme défini dans appsettings.json et ajouté via un middleware sur le pipeline. Mais les valeurs restent NULL, même si les mêmes éléments sont correctement remplis dans la colonne XML des propriétés.

J'ai donc les nouvelles propriétés attendues pour les utilisateurs authentifiés:

<properties>
    <property key="UserId">ff88ddb9-6f5a-4ad5-a2a8-1d016ff99398</property>
    <property key="UserName">ernst</property>
<properties>

Mais je veux également ajouter ces valeurs à leurs propres colonnes pour certaines optimisations de requête.

Le code

Le code est .NET Core 2.1+, et j'ai configuré Serilog comme indiqué sur https://github.com/serilog/serilog-aspnetcore/blob/dev/samples/SimpleWebSample/Program.cs =:

private static IConfiguration Configuration { get; } = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true)
            .AddEnvironmentVariables()
            .Build();

public static int Main(string[] args)
{
  Log.Logger = new LoggerConfiguration()
      .ReadFrom.Configuration(Configuration)
      .Enrich.FromLogContext()
      .MinimumLevel.Debug()
      .CreateLogger();
  try 
  {
    Log.Information($"Starting web Host in {Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"} environment, version {Util.Version.Long}");
    BuildWebHost(args).Run();
    return 0;
  }
  catch (Exception ex)
  {
    Log.Fatal(ex, "Host terminated unexpectedly");
    return 1;
  }
  finally
  {
    Log.CloseAndFlush();
  }
}

 private static IWebHost BuildWebHost(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>()
                .UseConfiguration(Configuration)
                .UseSerilog()
                .CaptureStartupErrors(true)
                .Build();

Pour ajouter les informations que j'utilise LogContext.PushProperty dans mon middleware.

Les éléments pertinents de la configuration:

"Serilog": {
    "Using": [ "Serilog.Sinks.MSSqlServer" ],
    "MinimumLevel": "Debug",
    "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
    "WriteTo": [
      {
        "Name": "MSSqlServer",
        "Args": {
          "connectionString": "Data Source=localhost;Database=MyDb;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
          "tableName": "SeriLog_Custom",
          "autoCreateSqlTable": true,
          "restrictedToMinimumLevel": "Information",
          "columnOptionsSection": {
            "customColumns": [
              {
                "ColumnName": "UserId",
                "DataType": "nvarchar",
                "DataLength": 450,
                "AllowNull": true
              },
              {
                "ColumnName": "UserName",
                "DataType": "nvarchar",
                "DataLength": 256,
                "AllowNull": true

              }
            ]
          }
        }
      }
    ]
  }

De plus, en plus de ne pas remplir les colonnes personnalisées, la base de données est également créée de manière standard sans ces colonnes, donc je les ai ajoutées à la main.

Cela pourrait indiquer un problème de configuration?

Le SQL pour créer la table:

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[SeriLog_Custom](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Message] [nvarchar](max) NULL,
    [MessageTemplate] [nvarchar](max) NULL,
    [Level] [nvarchar](128) NULL,
    [TimeStamp] [datetime] NOT NULL,
    [Exception] [nvarchar](max) NULL,
    [Properties] [xml] NULL,
    [UserId] [nvarchar](450) NULL,
    [UserName] [nvarchar](256) NULL,
 CONSTRAINT [PK_SeriLog_Custom] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

Maintenant, je peux obtenir les informations souhaitées avec:

SELECT [Id]
      ,[Message]
      ,[MessageTemplate]
      ,[Level]
      ,[TimeStamp]
      ,[Exception]
      ,[UserId]
      ,[UserName]
      ,[Properties].value('(//property[@key="UserName"]/node())[1]', 'nvarchar(max)') as UserName
      ,[Properties]
  FROM [ECSControl].[dbo].[SeriLog_ECMonitor]
  where [Properties].value('(//property[@key="UserName"]/node())[1]', 'nvarchar(max)') = 'ernst'
  order by id desc;

Mais je veux y accéder avec:

SELECT [Id]
      ,[Message]
      ,[MessageTemplate]
      ,[Level]
      ,[TimeStamp]
      ,[Exception]
      ,[UserId]
      ,[UserName]
      ,[Properties]
  FROM [ECSControl].[dbo].[SeriLog_ECMonitor]
  where  UserName = 'ernst'
  order by id desc;
10
Ernst

La dernière version stable de Serilog.Sinks.MSSqlServer (5.1.2) ne prend pas en charge Microsoft.Extensions.Configuration. La même chose avec la dernière version stable de Serilog.Settings.Configuration (2.6.1) ( ref ).

La mise à jour vers les versions préliminaires Serilog.Sinks.MSSqlServer 5.1.3-dev-00204 Et Serilog.Settings.Configuration 3.0.0-dev-00119 Résout ce problème.

10
Alex Riabov