Skip to content

Instantly share code, notes, and snippets.

@gubser
Created May 5, 2020 05:54
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 gubser/4853b209764be07704fc3d28a5a3afd2 to your computer and use it in GitHub Desktop.
Save gubser/4853b209764be07704fc3d28a5a3afd2 to your computer and use it in GitHub Desktop.
Simple console logging in F# (incomplete)
module Turns.Log
open System
open System.Threading.Tasks
open NodaTime
module Logging =
type LogLevel =
| Debug
| Info
| Warning
| Error
| Critical
type LogRecord = {
Level: LogLevel
Instant: Instant
Subsystem: string
Message: string
Extra: obj option
Completion: TaskCompletionSource<unit> option
}
let timeFormatter =
NodaTime.Text.InstantPattern.CreateWithInvariantCulture("uuuu'-'MM'-'dd'T'HH':'mm':'ss;FFF'Z'")
let logjson record =
let level =
match record.Level with
| LogLevel.Debug -> "debug"
| LogLevel.Info -> " info"
| LogLevel.Warning -> " warn"
| LogLevel.Error -> "error"
| LogLevel.Critical -> "critical"
let time = timeFormatter.Format(record.Instant)
printf "{ \"t\": \"%s\", \"l\": \"%s\", \"s\": %s, \"m\": %s }\n"
time
level
(Turns.Json.toJson record.Subsystem)
(Turns.Json.toJson record.Message)
let logconsole record =
let level =
match record.Level with
| LogLevel.Debug -> "DEBUG"
| LogLevel.Info -> " INFO"
| LogLevel.Warning -> Crayon.Output.BrightYellow " WARN"
| LogLevel.Error -> Crayon.Output.BrightRed "ERROR"
| LogLevel.Critical -> Crayon.Output.Red "CRITICAL"
let time = timeFormatter.Format(record.Instant)
let extra =
record.Extra
|> Option.map Turns.Json.toJson
|> Option.defaultValue ""
let printfunc =
match record.Level with
| LogLevel.Debug
| LogLevel.Info
| LogLevel.Warning -> printf
| LogLevel.Error
| LogLevel.Critical -> eprintf
printfunc "%s %s [%s] %s %s\n"
time
level
record.Subsystem
record.Message
extra
let logprinter =
MailboxProcessor.Start(fun inbox ->
let rec loop () = async {
let! record = inbox.Receive()
logconsole record
// logjson record
// in case completion is requested, we flush standard output
match record.Completion with
| Some tcs ->
Console.Out.Flush()
tcs.SetResult()
| None -> ()
return! loop ()
}
loop ()
)
let logfunc level subsystem extra completion message =
Logging.logprinter.Post({
Level = level
Instant = SystemClock.Instance.GetCurrentInstant()
Subsystem = subsystem
Message = message
Extra = extra
Completion = completion
})
let debug subsystem =
Printf.ksprintf (logfunc Logging.LogLevel.Debug subsystem None None)
let info subsystem =
Printf.ksprintf (logfunc Logging.LogLevel.Info subsystem None None)
let warning subsystem =
Printf.ksprintf (logfunc Logging.LogLevel.Warning subsystem None None)
let error subsystem =
Printf.ksprintf (logfunc Logging.LogLevel.Error subsystem None None)
let critical subsystem =
Printf.ksprintf (logfunc Logging.LogLevel.Critical subsystem None None)
let debugX subsystem extra =
Printf.ksprintf (logfunc Logging.LogLevel.Debug subsystem (Some extra) None)
let infoX subsystem extra =
Printf.ksprintf (logfunc Logging.LogLevel.Info subsystem (Some extra) None)
let warningX subsystem extra =
Printf.ksprintf (logfunc Logging.LogLevel.Warning subsystem (Some extra) None)
let errorX subsystem extra =
Printf.ksprintf (logfunc Logging.LogLevel.Error subsystem (Some extra) None)
let logCriticalX subsystem extra =
Printf.ksprintf (logfunc Logging.LogLevel.Critical subsystem (Some extra) None)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment