{-# LANGUAGE TemplateHaskellQuotes #-}

-- | functions for splicing in static information and creating log entries from it
module Unclog.Frontend
  ( -- * generic logging functions
    mkLogEntry

    -- * communicating with the backend
  , publishLogEntry

    -- * helpers
  , spliceLoc
  )
where

import Chronos.Types (Time)
import Data.ByteString (StrictByteString)
import Data.Text qualified as T
import Language.Haskell.TH.Syntax (Code, Lift (liftTyped), Loc (Loc), Quasi (qLocation), Quote, bindCode)
import Unclog.Common
import UnliftIO (STM, writeTChan)

spliceLoc :: (Quote q, Quasi q) => Code q Location
spliceLoc :: forall (q :: * -> *). (Quote q, Quasi q) => Code q Location
spliceLoc = (q Location -> (Location -> Code q Location) -> Code q Location)
-> (Location -> Code q Location) -> q Location -> Code q Location
forall a b c. (a -> b -> c) -> b -> a -> c
flip q Location -> (Location -> Code q Location) -> Code q Location
forall (m :: * -> *) a b.
Monad m =>
m a -> (a -> Code m b) -> Code m b
bindCode Location -> Code q Location
forall t (m :: * -> *). (Lift t, Quote m) => t -> Code m t
forall (m :: * -> *). Quote m => Location -> Code m Location
liftTyped do
  Loc String
_ String
p String
m (Int
pl, Int
pr) (Int, Int)
_ <- q Loc
forall (m :: * -> *). Quasi m => m Loc
qLocation
  Location -> q Location
forall a. a -> q a
forall (f :: * -> *) a. Applicative f => a -> f a
pure MkLocation {locpkg :: Text
locpkg = String -> Text
T.pack String
p, locmod :: Text
locmod = String -> Text
T.pack String
m, locpos :: Position
locpos = Int -> Int -> Position
MkPosition Int
pl Int
pr}

-- | given a 'LogChan', publish a log entry to it
publishLogEntry :: PLogChan -> LogEntry -> STM ()
publishLogEntry :: PLogChan -> LogEntry -> STM ()
publishLogEntry = TChan LogEntry -> LogEntry -> STM ()
forall a. TChan a -> a -> STM ()
writeTChan (TChan LogEntry -> LogEntry -> STM ())
-> (PLogChan -> TChan LogEntry) -> PLogChan -> LogEntry -> STM ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PLogChan -> TChan LogEntry
unPLogChan
{-# INLINE publishLogEntry #-}

-- | splice in the location and loglevel
mkLogEntry :: (Quote q, Quasi q) => LogLevel -> Code q (Time -> StrictByteString -> LogEntry)
mkLogEntry :: forall (q :: * -> *).
(Quote q, Quasi q) =>
LogLevel -> Code q (Time -> StrictByteString -> LogEntry)
mkLogEntry LogLevel
lvl =
  [||
  \p
ts p
entry -> do
    MkLogEntry
      { level :: LogLevel
level = LogLevel
lvl
      , timestamp :: Time
timestamp = p
ts
      , location :: Location
location = $$Code q Location
forall (q :: * -> *). (Quote q, Quasi q) => Code q Location
spliceLoc
      , payload :: StrictByteString
payload = p
entry
      }
  ||]