Created
November 19, 2021 14:47
-
-
Save isaacabraham/ba1bc33e99b14df0dd8bb5cfbb9dc703 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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