Skip to content

Expecto hooking provider and example #17

@ImaginaryDevelopment

Description

@ImaginaryDevelopment

Is your feature request related to a problem? Please describe.
There is no example showing hooking up to expecto. I imagine even a naive implementation of hooking expecto up to this would be very valuable for use or even to get eyes on it and hone it.

Describe the solution you'd like
I'd like to take the example I've worked out and figure out a good home for it in the project.

Describe alternatives you've considered
I've considered not sharing it, and I decided against it.

Additional context
I was told it was worth sharing :)

Some of the core code can live right here until a home is found:


module ELogging =
  open System
  open AutoUpdates.Server.Logging
  module EMsg = Expecto.Logging.Message
  type ELL = Expecto.Logging.LogLevel

  let addExnOpt exOpt msg =
      match exOpt with
      | None -> msg
      | Some ex -> msg |> EMsg.addExn ex
  let addValues (items:obj[]) msg =
      (msg,items |> Seq.mapi(fun i item -> i,item))
      ||> Seq.fold(fun msg (i,item) ->
        msg
        |> EMsg.setField (string i) item
      )

  let getLogLevel : LogLevel -> Expecto.Logging.LogLevel =
      function
      | LogLevel.Debug -> ELL.Debug
      | LogLevel.Error -> ELL.Error
      | LogLevel.Fatal -> ELL.Fatal
      | LogLevel.Info -> ELL.Info
      | LogLevel.Trace -> ELL.Verbose
      | LogLevel.Warn -> ELL.Warn
      | _ -> ELL.Warn

  // type Logger = LogLevel -> MessageThunk -> exn option -> obj array -> bool
  // Naive implementation, not that important, just need logging to actually work
  type ExpectoLogProvider () =
      let mutable contexts = ResizeArray<_>()
      let createDisp (name:string) =
          contexts.Add name
          let fullContext =
              contexts
              |> String.concat "."
          let x = Expecto.Logging.Log.create fullContext
          let logContextChange title =
              sprintf "%s %s" fullContext title
              |> EMsg.eventX
              |> x.log ELL.Info
              |> Async.RunSynchronously
          logContextChange "Starting"
          let deq () =
              logContextChange "Finished"

              if not <| contexts.Remove name then
                  let msg = sprintf "Could not find context %s in collection" name
                  x.log ELL.Error (EMsg.eventX msg)
                  |> Async.RunSynchronously
          { new IDisposable with
              member __.Dispose() = deq()
          }

      interface ILogProvider with
          override __.GetLogger(name:string): Logger =
              let x = Expecto.Logging.Log.create name
              fun ll mt exnOpt values ->
                  match mt with
                  | Some f ->
                      let ll = getLogLevel ll
                      x.log ll (fun ll ->
                          let message = f()
                          let msg = Expecto.Logging.Message.eventX message ll
                          match exnOpt with
                          | None -> msg
                          | Some ex -> msg |> Expecto.Logging.Message.addExn ex
                          |> addValues values

                      ) |> Async.RunSynchronously
                      true
                  | None -> false
          override __.OpenMappedContext (name:string) (o:obj) (b:bool) =
              createDisp name
          override __.OpenNestedContext name = createDisp name

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions