What logging framework is better to use in F# code

logary
net logging

I need to add logging to my F# project. For C# code we used: Log4net or NLog (possible two of the most popular logging frameworks for .Net).

What is the best choice to use in F# code? I mean, is there any specific logging framework written for usage in F# code?

Use Logary

https://github.com/logary/logary

Logary supports logging, metrics and distributed tracing for .Net Core.

Targets include: 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).

Further, you can expose a HTTP server for Proemetheus to scrape with Logary.Prometheus.

It also has a Dash service that supports real-time push of logs to your web browser.

Further, Logary Rutta is a sidecar container implementation or stand-alone log router for the cloud-native era.

Logary JS is a logging and metrics library for JavaScript that can ship into Logary Rutta on the server side, from where you can then furthr the logs to any of the available targets.

Logary Facade is an Apache 2-licensed facade you can copy-n-paste into all your C# and F# libraries and get high-quality console logging with.

Logary is written in F# for F# primarily.

Install-Package Logary

docs here

All of the above is free to use for non-commercial purposes. You can see the different licenses here.

NLog vs log4net vs Serilog: Compare .NET Logging Frameworks, Compare three of the most popular logging frameworks in the . It is possible to configure it using code, but it isn't well documented. Installing Serilog is slightly more complex than NLog or log4net because it At the moment he is interested in F# and how AI is going to change how we develop software. With quite a modest statement, loglevel presents itself a minimal logging framework that adds just the bare minimum that most applications need. It adds some proper level-based logging (trace/debug/info/warn/error) and filtering as to what is the minimum level to be displayed on the console.

As far as I know, they're the same for F#, i.e. there's nothing F# specific about them (whether good or bad). Aside from configuration, usage is pretty much the same for all logging libraries.

What you might want to add is printf-enabled logging, so instead of logger.DebugFormat("Hello {0}", "world") or logger.Debug(sprintf "Hello %s" "world") you can just do logger.Debugf "Hello %s" "world". Use type extensions and kprintf to do this.

To log or not to log, This example is taken from my Test-Driven Development with F# Pluralsight course, I strongly believe that in any well-designed code base, the core You should use an existing logging library such as Serilog, log4net, NLog, In reality, you probably want to use more granular flags than a single log flag,  Open the Visual Studio Code settings (Code > Preferences > Settings). Search for the term F# Script. Click the checkbox that says FSharp: use SDK scripts. This is currently necessary due to some legacy behaviors in .NET Framework-based scripting that don't work with .NET Core scripting, and Ionide is currently striving for that backwards compatibility.

I did code something like this (using verbosal syntax):

#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

usage:

"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");

produces:

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

just simple and eazy to use for me.

Logging in F# (or any other functional language really) : fsharp, We have been using Serilog as our logger of choice in our (ServiceStack) I'm asking here instead of on github because reddit is more informal and I'm also not frameworks (Blazor for C# and Bolero for F# which has Blazor-compatibility). I have a feeling that F# is especially optimized for handling in-code complexity in​  So make sure that your logging framework gives you this ability and, hopefully, even defaults to doing it. The Future Is Bright. There’s no getting around it — choosing a logging framework is an important architectural decision. Your code will use it a lot, creating enormous impact on both performance and code maintainability.

mvkara/loggerwrapper-fsharp: Library to wrap most .NET , NET logging frameworks giving them a functional F# style API. Contains handly utility functions that are useful if you are in a project that requires you to use a  For non-primitive types, the .NET formatting functions only support using ToString(), but printf supports native F# types using the %A specifier: // tuple printing let t = ( 1 , 2 ) Console . WriteLine ( "A tuple: {0}" , t ) printfn "A tuple: %A" t // record printing type Person = { First : string ; Last : string } let johnDoe = { First = "John" ; Last = "Doe" } Console .

logary/logary: Logs and metrics are one! Professional , logging library which you can do health and metrics for .Net. Full support for Structured/Semantic Logging; F# idiomatic code; Using C#? Then Logary.​CSharp  Using F# 5 preview. You can use F# 5 preview via the .NET 5 preview SDK, or through the .NET and Jupyter Notebooks support. If you’re using the .NET 5 preview SDK, check out a sample repository showing off some of what you can do with F# 5. You can play with each of the features there instead of starting from scratch.

Partial Application · F# for Fun and Profit, Ideally, I'd like to make this more generic so that I can choose how logging is To use this in practice, we just define the functions and pass them in to the library Here's the F# code translated into C# (note that I had to specify the types for  FsLibLog ★ 26 ⧗ 0 - FsLibLog is a single file you can copy paste or add through Paket Github dependencies to provide your F# library with a logging abstraction. [MIT] Logary ★ 259 ⧗ 0 - Logary is a high performance, multi-target logging, metric, tracing and health-check library for mono and .Net.

Comments
  • full disclosure: Henrik is the main contributor to logary.
  • Also, since this answer was written, it is important to note that Logary is no longer open source for those of us using a Microsoft "web stack", which is most of us.
  • @BenCollins This is lie; it's open source but the license for those using a MSFT web stack is a commercial one. It will always be open source.
  • @Henrik I don't mean you any disrespect, and I'm not attacking Logary, but if a library requires a commercial license for a category of users, then it seems to me that it's not open source by definition (at least for those users).
  • Open source is not the same as free open source. The source code is freely available and open to modification; it's just not allowed to be used in all circumstances. Otherwise, you'd say GNU v3 is also not open source, because it's not allowed to be used in the circumstance of commercial software — which is an equally absurd statement, don't you think?
  • Thank you for your answer - this can be used as solution to prepare my own logger, based on Log4Net with F# similar syntax
  • I often use kprintf to make a set of functions like you suggest, but I make them post to a MailboxProcessor that writes asynchronously to whatever underlying log framework I happen to be using - which may just be writing to the console in different colors for a simple command-line utility.
  • i asked a similar question here: stackoverflow.com/questions/5277902/printf-style-logging-for-f feel free to elaborate :)