-- |Description: Internal
module Polysemy.Log.Data.LogEntry where

import Data.Time (UTCTime)
import Data.Time.Calendar (Day)
import qualified Polysemy.Time as Time
import Polysemy.Time (GhcTime)

-- |Metadata wrapper for a log message.
data LogEntry a =
  LogEntry {
    forall a. LogEntry a -> a
message :: !a,
    -- |The time at which the log entry was created.
    forall a. LogEntry a -> UTCTime
time :: !UTCTime,
    -- |The call stack of the function in which the entry was created.
    forall a. LogEntry a -> CallStack
source :: !CallStack
  }
  deriving (Int -> LogEntry a -> ShowS
[LogEntry a] -> ShowS
LogEntry a -> String
(Int -> LogEntry a -> ShowS)
-> (LogEntry a -> String)
-> ([LogEntry a] -> ShowS)
-> Show (LogEntry a)
forall a. Show a => Int -> LogEntry a -> ShowS
forall a. Show a => [LogEntry a] -> ShowS
forall a. Show a => LogEntry a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [LogEntry a] -> ShowS
$cshowList :: forall a. Show a => [LogEntry a] -> ShowS
show :: LogEntry a -> String
$cshow :: forall a. Show a => LogEntry a -> String
showsPrec :: Int -> LogEntry a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> LogEntry a -> ShowS
Show)

-- |Add call stack and timestamp to a message and wrap it with 'LogEntry'.
annotate ::
  HasCallStack =>
  Member GhcTime r =>
  a ->
  Sem r (LogEntry a)
annotate :: forall (r :: EffectRow) a.
(HasCallStack, Member GhcTime r) =>
a -> Sem r (LogEntry a)
annotate a
msg = do
  UTCTime
time <- forall t d (r :: EffectRow). Member (Time t d) r => Sem r t
Time.now @UTCTime @Day
  pure (a -> UTCTime -> CallStack -> LogEntry a
forall a. a -> UTCTime -> CallStack -> LogEntry a
LogEntry a
msg UTCTime
time CallStack
HasCallStack => CallStack
callStack)