什么日志框架最好在F#代码中使用

时间:2011-03-10 09:23:50

标签: logging f#

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

在F#代码中使用的最佳选择是什么? 我的意思是,是否有任何特定的日志框架编写用于F#代码?

3 个答案:

答案 0 :(得分:12)

据我所知,它们对于F#来说是相同的,即F#没有特定的关于它们(无论好坏)。除配置外,所有日志记录库的使用情况基本相同。

您可能想要添加的内容是支持printf的日志记录,因此您可以logger.DebugFormat("Hello {0}", "world")logger.Debug(sprintf "Hello %s" "world")代替logger.Debugf "Hello %s" "world"或{{1}}。使用type extensionskprintf执行此操作。

答案 1 :(得分:12)

使用Logary

https://github.com/logary/logary

Logary支持.Net Core的日志记录,指标和分布式跟踪。

目标包括:TextWriter,控制台,LiterateConsole,调试器,GCP Pub / Sub,GCP BigQuery,GCP Stackdriver,Jaeger,TCP(发货人),UDP(发货人),ZeroMQ(发货人)Elasticsearch,Graphite / statsd,elmah.io ,Aliyun,Azure ApplicationInsights,Mixpanel(商业),OpsGenie(商业),服务器发送事件(网络推送)。

此外,您可以将Proemetheus的HTTP服务器暴露给Logary.Prometheus。

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

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

Logary JS是一个用于JavaScript的日志记录和度量库,可以在服务器端发送到Logary Rutta,然后您可以将日志更新到任何可用目标。

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

Logary用F#编写,主要用于F#。

Install-Package Logary

docs here

以上所有内容均可免费用于非商业用途。您可以在此处看到不同的licenses

答案 2 :(得分:1)

我做了类似这样的代码(使用冗长的语法):

#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

简单易用。