Elegant way to switch off logging F#

Viewed 175

In my F# code I have a lot of logging. Something like this

logger.Log (sprintf "%A" (this.GetSomething parameters))

It all works well but the performance is low even with NullLogger due to a lot of sprintf calls. The string parameter for the log call is fully formed and then beign ignored at the end inside Log function

Is there a good way to completely switch off logging? Of course I could do preprocessor directives (are there such thing in F#?) or somehow use 'if flag then ....' but I am wondering if there is a F# magic which would do it nicely for me?

1 Answers

I think you can do this by using the Conditional("SYMBOL") attribute. The Log method may or may not already have this (as this is a standard .NET attribute). If you apply Conditional attribute on a method, the compiler will only compile the call when the attribute is specified - so you can use Conditional("DEBUG") to completely remove the call unless you compile with --define:DEBUG. Most importantly, this also removes all the code computing the argument. For example:

type Logger() = 
  [<System.Diagnostics.Conditional("DEBUG")>]
  member x.Log(s:string) = printfn "%s" s

let slowprintf f =
  Printf.kprintf (fun k -> printfn "SLOWPRINTF!"; k) f

let l = Logger()
l.Log(slowprintf "Yo %d" (System.Random().Next()))

If you compile this with --define:DEBUG, it prints SLOWPRINTF! (when formatting) and then Yo xyz with some random number (when logging). But without --define:DEBUG it does not print anything - not even the message from slowprintf.

Related