I have a utility function that combines error message logging (including string formatting) with raising an exception (either using an raiseexisting exception or calling failwithusing a formatted error message similar to the logAndFailWithf function below (although it actually uses a logging framework, not writing to a text file):
let logAndFailWithf exOpt =
let logFile = new StreamWriter("log.txt")
Printf.ksprintf <| fun message ->
try match exOpt with
| Some ex ->
logFile.WriteLine("{0}\r\n{1}", message, ex)
raise <| Exception(message, ex)
| None ->
logFile.WriteLine(message)
failwith message
finally logFile.Close()
val logAndFailWithf : exOpt:#exn option -> (Printf.StringFormat<'b,'c> -> 'b)
This function works fine if called directly, as in this simple example:
let s = "123x"
let x = try Int32.Parse s
with | ex -> logAndFailWithf (Some ex) "Failed to parse string s: %s" s
System.Exception: Failed to parse string s: "123x"
System.FormatException: Input string was not in a correct format.
at System.Number.StringToNumber(String str, NumberStyles options,
NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)
However, in a real scenario, the logging function is passed to another function that uses it to record and throw whenever it encounters this exception, as shown below:
let exmaple param1 param2 (log: exn option -> Printf.StringFormat<_,_> -> _) =
let x = try Int32.Parse param1
with | ex -> log (Some ex) "Failed to parse param1: \"%s\"" param1
let y = try Int64.Parse param2
with | ex -> log (Some ex) "Failed to parse param2: \"%s\"" param2
printfn "Successfully Parsed Parameters: param1 = %d; param2 = %d" x y
let binding (let y = ...) :
error FS0001: This expression was expected to have type
'int64'
but here has type
'int'
, , ( int64 y int x), log, logAndFailWithf , .
, ?