c# - 如何将 Serilog.Log.ForContext 与 F# 函数或 C# 方法一起使用

标签 c# f# serilog

使用 Serilog和F#如何使用.ForContext有功能吗?它似乎只接受类型类:

type A()=
  log = Serilog.Log.ForContext<A>() // ✅
let f _ =
  log = Serilog.Log.ForContext<f>() // compile error
  log = Serilog.Log.ForContext(f.GetType()) // the information is not the same as A where it gives module + type path
添加 F# 函数或 C# 方法的上下文的正确方法是什么(我认为应该是同一个问题)?

到目前为止,我的解决方案一直在使用这个函数,它返回 SourceContext 就像使用一个类( moduleFullName+className ):
let logFromFn _ =
  Serilog.Log.ForContext
    ("SourceContext",
     StackTrace().GetFrame(1).GetMethod().DeclaringType
     |> fun dt -> dt.FullName + "+" + dt.Name)
  • this answer 中所述,它可能很昂贵,我在整个程序中会调用一次的地方使用它。
  • 它在模块内的 F# 函数中运行良好,例如在入口点文件中不太好,它返回 program+program
  • 最佳答案

    方法没有 Type与它们相关联,因此您不能使用 ForContext<T>() 中的任何一个或 ForContext(Type type)过载。由于 F# 模块中的函数被编译为静态类(模块)内的静态方法,因此同样适用于它们。作为一个简单的替代方法,您可以设置 SourceContext自己的属性(property):

    let propName = Serilog.Core.Constants.SourceContextPropertyName
    Log.ForContext(propName, "App.Class.Method")
    Log.ForContext(propName, "App.Module.function")
    
    如果您想对重命名操作更加健壮,您可以执行以下操作:
    class Class
    {
        public void Method()
        {
            var source = $"{typeof(Class).FullName}.{nameof(Method)}";
            var logger = Log.ForContext(Core.Constants.SourceContextPropertyName, source);
            // ...
        }
    }
    
    module Module =
        // It's a bit fiddly to get the module type in F#, but here's one
        // approach (credit https://stackoverflow.com/a/14706890/7694577).
        type private Marker = interface end
        let private moduleType = typeof<Marker>.DeclaringType
    
        let loggerFor name =
            let source = sprintf "%s.%s" moduleType.FullName name
            let propName = Serilog.Core.Constants.SourceContextPropertyName
            Log.ForContext(propName, source)
        
    
        // Requires the `nameof` operator from F# 4.7 preview.
        // The function needs to be recursive since it is referenced when calling `nameof`.
        let rec func () =
            let logger = loggerFor (nameof func)
            // ...
    
    我要补充一点,通常类/模块名称足以确定消息的来源,因此我建议从源上下文中省略方法/函数名称。这将允许您使用 ForContext<T>()ForContext(Type type)重载,因此会大大简化事情。

    关于c# - 如何将 Serilog.Log.ForContext 与 F# 函数或 C# 方法一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63746000/

    相关文章:

    c# - trim() 一个xml文档中所有xml元素和属性的值使用c#

    .net - 类型不匹配错误。 F# 类型推断失败?

    f# - 从控制台读取字符串而不使用 for 循环

    visual-studio - 为什么Deedle的Frame.X静态方法在VS 2017中生成警告?

    c# - 与 ManualResetEvent 同步时出现问题

    c# - 在 azure 网络应用程序中 File.Exists 返回 false 实际上文件存在

    c# - 我应该如何在不实例化不必要地缓存的对象的情况下填充 MemoryCache?

    elasticsearch - 使用 Elasticsearch 和 serilog 翻转索引

    file - Serilog 不写入配置从 Console CORE 3 App 中的 appsettings.json 加载的文件

    asp.net-web-api - 任何使用 Serilog.Extras.MSOwin 的人