“向导应包含32位数字”,并且sql server sink出现serilog错误

问题描述 投票:0回答:1

我偶尔在MSSQLServer接收器中收到此错误。我看不到这个GUID有什么问题。有任何想法吗?我已经在每个地方都验证过,我可以找到源guid的数据类型是“ Guid”而不是字符串。我只是有些迷惑。

向导应包含32个数字,带4个破折号(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)。无法在用户ID列中存储。预期的类型为Guid。

此示例中的向导为:

7526f485-ec2d-4ec8-bd73-12a7d1c49a5d
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

似乎要将模板与我匹配?

更多详细信息:这是一个偶然的问题,但是当它出现时,它会出现很多。它似乎与特定的Guid有关。大多数Guid都很好,但是一小部分有此问题。我们的应用每天记录数千条消息,但是由于问题,这些消息并未记录下来,因此我很难准确地找到导致此错误的特定日志的来源。但是,我们使用集中式日志记录方法,该方法运行如下所示。该测试对我来说是合格的,但它反映了我们通常用于日志记录的设置和代码,通常可以成功。正如我所说的,这是一个间歇性问题:

    [Fact]
    public void Foobar()
    {
        // arrange
        var columnOptions = new ColumnOptions
        {
            AdditionalColumns = new Collection<SqlColumn>
            {
                new SqlColumn {DataType = SqlDbType.UniqueIdentifier, ColumnName = "UserId"},
            },

        };
        columnOptions.Store.Remove(StandardColumn.MessageTemplate);
        columnOptions.Store.Remove(StandardColumn.Properties);
        columnOptions.Store.Remove(StandardColumn.LogEvent);
        columnOptions.Properties.ExcludeAdditionalProperties = true;

        var badGuid = new Guid("7526f485-ec2d-4ec8-bd73-12a7d1c49a5d");

        var connectionString = "Server=(localdb)\\MSSQLLocalDB;Database=SomeDb;Trusted_Connection=True;MultipleActiveResultSets=true";

        var logConfiguration = new LoggerConfiguration()
            .MinimumLevel.Information()
            .Enrich.FromLogContext()
            .WriteTo.MSSqlServer(connectionString, "Logs",
                restrictedToMinimumLevel: LogEventLevel.Information, autoCreateSqlTable: false,
                columnOptions: columnOptions)
            .WriteTo.Console(restrictedToMinimumLevel: LogEventLevel.Information);
        Log.Logger = logConfiguration.CreateLogger();

        // Suspect the issue is with this line
        LogContext.PushProperty("UserId", badGuid);

        // Best practice would be to do something like this:
        // using (LogContext.PushProperty("UserId", badGuid)
        // {
             Log.Logger.Information(new FormatException("Foobar"),"This is a test");
        // }
        Log.CloseAndFlush();
    }

自构建此测试代码以来,我注意到的一件事是,没有捕获和处置UserId属性的“ PushProperty”。由于在这种情况下行为为"undefined",所以我还是倾向于对其进行修复,以查看问题是否消失。

完整堆栈:

2020-04-20T08:38:17.5145399Z Exception while emitting periodic batch from Serilog.Sinks.MSSqlServer.MSSqlServerSink: System.ArgumentException: Guid should contain 32 digits with 4 dashes (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).Couldn't store <"7526f485-ec2d-4ec8-bd73-12a7d1c49a5d"> in UserId Column.  Expected type is Guid.
 ---> System.FormatException: Guid should contain 32 digits with 4 dashes (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).
   at System.Guid.GuidResult.SetFailure(Boolean overflow, String failureMessageID)
   at System.Guid.TryParseExactD(ReadOnlySpan`1 guidString, GuidResult& result)
   at System.Guid.TryParseGuid(ReadOnlySpan`1 guidString, GuidResult& result)
   at System.Guid..ctor(String g)
   at System.Data.Common.ObjectStorage.Set(Int32 recordNo, Object value)
   at System.Data.DataColumn.set_Item(Int32 record, Object value)
   --- End of inner exception stack trace ---
   at System.Data.DataColumn.set_Item(Int32 record, Object value)
   at System.Data.DataRow.set_Item(DataColumn column, Object value)
   at Serilog.Sinks.MSSqlServer.MSSqlServerSink.FillDataTable(IEnumerable`1 events)
   at Serilog.Sinks.MSSqlServer.MSSqlServerSink.EmitBatchAsync(IEnumerable`1 events)
   at Serilog.Sinks.PeriodicBatching.PeriodicBatchingSink.OnTick()
serilog
1个回答
0
投票

我在上面的特定代码中看不到任何明显的问题会导致此问题。您将在设置Serilog之前调用PushProperty的事实会改变(即先设置Serilog,然后再调用PushProperty),但这似乎并不是您遇到问题的根本原因。

我的猜测是,您有一些代码路径将UserId记录为string,而不是Guid。 Serilog期望使用Guid值类型,因此,如果为它提供stringGuid表示形式,它将不起作用,并且会为您提供这种类型的异常。

也许在代码库中的某个位置,您正在登录之前在.ToString上调用UserId?或者也许使用字符串插值Log.Information("User is {UserId}", $"{UserId}");

例如:

var badGuid = "7526f485-ec2d- 4ec8-bd73-12a7d1c49a5d";
LogContext.PushProperty("UserId", badGuid);

Log.Information(new FormatException("Foobar"), "This is a test");

或者甚至只是直接使用UserId属性记录消息:

var badGuid = "7526f485-ec2d-4ec8-bd73-12a7d1c49a5d";
Log.Information("The {UserId} is doing work", badGuid);

上面的两个代码片段都会抛出与您相同的异常,因为它们使用的是string值,而不是实际的Guid值。

© www.soinside.com 2019 - 2024. All rights reserved.