Skip to content

Instantly share code, notes, and snippets.

@isaacabraham
Created November 19, 2021 14:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save isaacabraham/ba1bc33e99b14df0dd8bb5cfbb9dc703 to your computer and use it in GitHub Desktop.
Save isaacabraham/ba1bc33e99b14df0dd8bb5cfbb9dc703 to your computer and use it in GitHub Desktop.
module Decorators =
type FnDetails<'T> = { Name : string; Args : 'T }
type DecoratedFunction<'a, 'b> = FnDetails<'a> -> 'b
/// Logs the arguments and result of any function call.
let logger next details =
fooLogger.LogInformation ("Inside {Name}, Args {Args}", details.Name, details.Args)
let result = next details
fooLogger.LogInformation ("Result was {Result}.", $"%A{result}")
result
/// Times any function call.
let timer next details =
let sw = System.Diagnostics.Stopwatch.StartNew()
let result = next details
sw.Stop()
fooLogger.LogInformation ("{functionName} took {Time}.", details.Name, sw.Elapsed)
result
/// Handles exceptions into a generic Result type of <T, exn>.
let asResult next (details:FnDetails<_>) =
try
next details |> Ok
with
ex -> Error ex
/// Takes a regular function and "lifts" it into a decorator that can be pipelined.
let lift fn details = fn details.Args
/// Takes a regular function and "lifts" it into a decorator that can be pipelined.
let (!!) = lift
let complete next name args = next { Name = name; Args = args }
/// Real function - doing some "business logic" logging but nothing more.
let addNumbers (logger:ILogger<_>) (a:int, b) =
logger.LogDebug "I'm doing the logic..."
if a < 10 then failwith "Bad data!"
a + b
let divideNumbers (logger:ILogger<_>) (a:int, b) =
logger.LogDebug "I'm dividing stuff..."
a / b
open Decorators
let decoratedAddNumbers = !!(addNumbers barLogger) |> asResult |> timer |> logger |> complete
let x = decoratedAddNumbers "DoStuff" (15, 10)
let decoratedDivide = !!(divideNumbers barLogger) |> asResult |> complete
let answer = decoratedDivide "Divide" (15, 0)
printfn $"Answer: {answer}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment