c# - 解构 EF 对象会导致 Serilog 内存不足

标签 c# asp.net-mvc entity-framework serilog

我正在为使用 Entity Framework 的 SaaS 应用程序测试 Serilog。
我注意到如果尚未处理加载对象的上下文,Serilog 无法处理解构 EF 对象。

Supplier supplier = context.Supplier.Find(6100);
Log.Information("This works and the cost for ToString() is negligible {supp}", supplier);

Log.Fatal("This will cause an Out of Memory error {@supp}", supplier);

Serilog 将尝试延迟加载整个数据库,应用程序将挂起一分钟并崩溃。 Serilog 日志文件将报告 OutOfMemoryException

如何防止其他开发人员不小心执行以下操作并导致意外挂起/崩溃?
if(veryRarelyOccuringEvent)
    Log.Information("Supplier {@supplier} just did something, supplier)

我所做的是使用解构策略来防止所有解构,
我宁愿让开发人员明确声明 ToString 方法而不是使用 @。当然,我们可以决定不使用@-operator,但是如果有人忘记了并且应用程序因此而崩溃怎么办? @ 在代码审查中很容易错过。我不想为 Serilog 操作构造一个包装器只是为了防止使用 @。

以下将阻止使用@-operator:
            Log.Logger = new LoggerConfiguration()
                .Destructure.With<PreventDestructure>()
            ...

并且只会返回 {}。但是有没有比下面的代码更简单的方法?
public class PreventDestructure : IDestructuringPolicy {
    public bool TryDestructure(
        object value,
        ILogEventPropertyValueFactory propertyValueFactory,
        out LogEventPropertyValue result) {



        List<LogEventProperty> fieldsWithValues;
        fieldsWithValues = new List<LogEventProperty>();
        result = new StructureValue(fieldsWithValues);

        return true;

    }
}

第二个问题:有没有办法指示 Serilog 在日志事件中花费最大 XXXms?如果我使用数据库接收器并且数据库处于离线状态怎么办?如果我使用 AI 接收器并且无法访问 ApplicationInsights 等?

最佳答案

我猜测 Serilog 由于实体中的导航属性而挂起,这很容易导致整个数据库被加载。我找到了 an issue on a Serilog似乎描述了相同问题的项目。

在那个问题上,他们说:

Serilog does already have a maximum depth limit; it's set to 10 by default but you can use Destructure.ToMaximumDepth(n) to reduce it.



您可以尝试将其设置为 1,以防止加载相关实体。但是,我个人认为这不是一个理想的解决方案。

还有this NuGet package允许您使用 NotLogged您不想记录的属性或字段的属性。哪个可行,但如果您在某处的导航属性上忘记了它,仍然很容易错过。

由于 Serilog 为您提供了自定义解构处理方式的选项。您可以编写自己的处理程序来满足您的所有要求,例如最大时间花费日志记录,或者只是让它记录堆栈跟踪,说明它试图将对象解构为故障安全。但这取决于你。

关于c# - 解构 EF 对象会导致 Serilog 内存不足,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48516514/

相关文章:

c# - 如何在设计时不知道要选择的属性的名称的情况下编写 linq select 语句?

asp.net-mvc - 打开子表单时应该如何保存和重新填充表单数据?

c# - 在洋葱架构中放置 View 模型/DTO

c# - InstallShield Basic MSI Project 安装程序在安装升级后丢失 "Log On As"

c# - StreamWriter 用新文本替换行

c# - Asp.net core 3.1 将 Url 中的斜杠 (/) 替换为问题 Marq (?)

asp.net - 访问 ActionFilterAttribute 中的 Session.SessionID

c# - Microsoft Entity Framework 中使用的原始 SQL 查询是否返回对象?

entity-framework - 如何解决警告 : The element 'entityFramework' has invalid child element 'providers' . 预期的可能元素列表: 'contexts'

c# - TPL 数据流,替代 JoinBlock 限制?