【问题标题】:What logging framework is better to use in F# code [closed]在 F# 代码中使用哪种日志记录框架更好[关闭]
【发布时间】:2011-03-10 09:23:49
【问题描述】:

我需要将日志记录添加到我的 F# 项目中。 对于我们使用的 C# 代码:Log4net 或 NLog(可能是 .Net 最流行的两个日志框架)。

在 F# 代码中使用的最佳选择是什么? 我的意思是,是否有专门为 F# 代码编写的日志框架?

【问题讨论】:

    标签: logging f#


    【解决方案1】:

    Logary 库

    https://github.com/logary/logary

    我是 Logary 的作者,它支持 .Net Core 的日志记录、指标和分布式跟踪。

    目标包括:TextWriter、Console、LiterateConsole、Debugger、GCP Pub/Sub、GCP BigQuery、GCP Stackdriver、Jaeger、TCP(Shipper)、UDP(Shipper)、ZeroMQ(Shipper)Elasticsearch、Graphite/statsd、elmah.io , Aliyun, Azure ApplicationInsights, Mixpanel (commercial), OpsGenie (commercial), Server-sent-events (web push)。

    此外,您可以公开 HTTP 服务器以供 Proemetheus 使用 Logary.Prometheus 进行抓取。

    它还有一个Dash service,支持将日志实时推送到您的网络浏览器。

    此外,Logary Rutta 是云原生时代的 sidecar 容器实现或独立日志路由器。

    Logary JS 是一个用于 JavaScript 的日志记录和指标库,可以发送到服务器端的 Logary Rutta,然后您可以从那里将日志进一步发送到任何可用的目标。

    Logary Facade 是一个获得 Apache 2 许可的外观,您可以将其复制并粘贴到所有 C# 和 F# 库中,并获得高质量的控制台日志记录。

    Logary 主要是为 F# 用 F# 编写的。

    Install-Package Logary
    

    docs here

    以上所有内容均可免费用于非商业目的。你可以在这里看到不同的licenses

    【讨论】:

    • 另外,由于编写了这个答案,重要的是要注意 Logary 不再对我们这些使用微软“网络堆栈”的人(我们大多数人)来说是开源的。
    • @BenCollins 这是谎言;它是开源的,但使用 MSFT 网络堆栈的许可证是商业许可证。它永远是开源的。
    • @Henrik 我并不是对你有任何不尊重,我也不是在攻击 Logary,但如果图书馆需要为一类用户提供商业许可,那么在我看来它没有开放根据定义来源(至少对于那些用户而言)。
    • 开源不等于免费开源。源代码免费提供并开放修改;它只是不允许在所有情况下使用。否则,你会说 GNU v3 也不是开源的,因为它不允许在商业软件的情况下使用——这同样是一种荒谬的说法,你不觉得吗?
    • GPL 不禁止商业用途;它具有重新分配的条件。严格来说,Logary 不再符合 OSI 对开源的定义,所以我不认为我在这里是荒谬的。
    【解决方案2】:

    我编写了类似这样的代码(使用详细语法):

    #light "off"
    open System.Runtime.CompilerServices
    
    let inline (|?) (a: 'a option) b = if a.IsSome      then a.Value else b; // coalesce operator
      type T() = class
            static member private printLog(par) =
               match ( par) with
                    | msg, Some m, Some p, Some l  -> (
                        let pl = Array.head  (Array.rev( string(p).Split([|'\\';'/'|]))) in
                        printfn "at %s(%s: line %d) %s" m pl l msg
                        )
                    | msg, _,_,_ -> printfn "at ?? %s" msg
            static member LOG(msg: string, ?a:obj,
                              [<CallerMemberName>] ?memberName: string,
                              [<CallerFilePath>] ?path: string,
                              [<CallerLineNumber>] ?line: int) = match a with
                        | Some a -> (match a with
                              | :? int as i -> T.printLog((sprintf "%s %d" msg i), memberName, path,line)
                              | :? float as f -> T.printLog((sprintf "%s %f" msg f), memberName, path,line)
                              | _ -> T.printLog((sprintf "%s %A" msg a), memberName, path,line)
                                        )
                        | None -> T.printLog(msg, memberName, path,line)
              static member EXIT(?msg:string, [<CallerMemberName>] ?memberName: string,
                              [<CallerFilePath>] ?path: string,
                              [<CallerLineNumber>] ?line: int) =
                      printf "Exiting ... ";
                      T.printLog((msg |? "Giving up!"), memberName, path,line);
                      exit 1
       end
    

    用法:

    "text pushed in" |> T.LOG;
    T.LOG "just text at line ";
    T.LOG ("just text at line in par");
    T.LOG ("string ", "text i got");
    T.LOG ("int ", 1);
    T.LOG ("tuple ", (1,2));
    let  msg  = Some "existing optional value" in 
    printfn """ (msg |? "this is default value\")  --->  %A""" (msg |? "d
    T.EXIT( "after all test done no TODO new extentions");
    

    产生:

    at testit(TautoLogics.fs: line 49) text pushed in
    at testit(TautoLogics.fs: line 52) just text at line
    at testit(TautoLogics.fs: line 53) just text at line in par
    at testit(TautoLogics.fs: line 54) string  "text i got"
    at testit(TautoLogics.fs: line 55) int  1
    at testit(TautoLogics.fs: line 56) tuple  (1, 2)
    '(msg |? "this is default value\")  --->  "existing optional value"
    Exiting ... at testit(TautoLogics.fs: line 63) after all test done
    

    对我来说简单易用。

    【讨论】:

      【解决方案3】:

      据我所知,它们对于 F# 是相同的,即它们没有特定的 F#(无论好坏)。除了配置之外,所有日志库的使用几乎相同。

      您可能想要添加的是启用 printf 的日志记录,因此您可以使用 logger.Debugf "Hello %s" "world" 而不是 logger.DebugFormat("Hello {0}", "world")logger.Debug(sprintf "Hello %s" "world")。使用type extensionskprintf 来执行此操作。

      【讨论】:

      • 感谢您的回答 - 这可以用作准备我自己的记录器的解决方案,基于具有 F# 类似语法的 Log4Net
      • 我经常使用kprintf 来制作您建议的一组函数,但我将它们发布到MailboxProcessor,该MailboxProcessor 异步写入我碰巧使用的任何底层日志框架 - 这可能只需为简单的命令行实用程序以不同颜色写入控制台即可。
      • 我在这里问了一个类似的问题:stackoverflow.com/questions/5277902/printf-style-logging-for-f 随意详细说明:)
      猜你喜欢
      • 2013-12-11
      • 2012-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多