{-# LANGUAGE TemplateHaskellQuotes #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}

-- | The 'IO' + @Json@ frontend. Using 'MonadUnliftIO' to abstract over things in 'IO'
module Unclog.IO.Json
  ( -- * logging functions for different log levels
    debug
  , info
  , warn
  , fatal

    -- * run the frontend
  , withLoggingWithSubscribers

    -- * helpers
  , logJson
  )
where

import Chronos (now)
import Data.Aeson (Value (Object), encode)
import Data.ByteString qualified as BS
import Language.Haskell.TH.Syntax (Exp, Q, unTypeCode)
import Unclog.Common (LogLevel (..))
import Unclog.Frontend (mkLogEntry, publishLogEntry)
import Unclog.Subscriber (withLoggingWithSubscribers)
import UnliftIO (atomically, liftIO)

logJson :: LogLevel -> Q Exp
logJson :: LogLevel -> Q Exp
logJson LogLevel
lvl =
  [|
    \chan obj -> liftIO do
      ts <- now -- TODO(mangoiv): should be cached
      let entry = $(Code Q (Time -> StrictByteString -> LogEntry) -> Q Exp
forall a (m :: * -> *). Quote m => Code m a -> m Exp
unTypeCode (Code Q (Time -> StrictByteString -> LogEntry) -> Q Exp)
-> Code Q (Time -> StrictByteString -> LogEntry) -> Q Exp
forall a b. (a -> b) -> a -> b
$ LogLevel -> Code Q (Time -> StrictByteString -> LogEntry)
forall (q :: * -> *).
(Quote q, Quasi q) =>
LogLevel -> Code q (Time -> StrictByteString -> LogEntry)
mkLogEntry LogLevel
lvl) ts (BS.toStrict . encode $ Object obj)
      atomically $ publishLogEntry chan entry
    |]

debug :: Q Exp
debug :: Q Exp
debug = LogLevel -> Q Exp
logJson LogLevel
Debug

info :: Q Exp
info :: Q Exp
info = LogLevel -> Q Exp
logJson LogLevel
Info

warn :: Q Exp
warn :: Q Exp
warn = LogLevel -> Q Exp
logJson LogLevel
Warn

fatal :: Q Exp
fatal :: Q Exp
fatal = LogLevel -> Q Exp
logJson LogLevel
Fatal