Move to another representation

This commit is contained in:
Stefan Risberg 2024-07-15 15:46:17 +02:00
parent a43eb4fe62
commit c1c18fdd65

View File

@ -1,3 +1,5 @@
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE PatternSynonyms #-}
module Effects.Log ( module Effects.Log (
@ -10,17 +12,17 @@ module Effects.Log (
Log, Log,
log, log,
LogData (..), LogData (..),
ls,
) where ) where
import Colog.Core import Colog.Core
import Data.String (IsString (..))
import Data.String.Conv
import Data.Text (Text, justifyLeft) import Data.Text (Text, justifyLeft)
import Data.Text qualified as T import Data.Text qualified as T
import Data.Text.IO qualified as T import Data.Text.IO qualified as T
import Data.Text.Lazy qualified as LT import Data.Text.Lazy qualified as LT
import Data.Text.Lazy.Builder qualified as T import Data.Text.Lazy.Builder qualified as T
import Data.Text.Encoding qualified as T
import Data.Text.Lazy.Encoding qualified as LT
import Data.Text.Encoding.Error qualified as T
import Effectful import Effectful
import Effectful.Concurrent.QSem import Effectful.Concurrent.QSem
import Effectful.Dispatch.Dynamic import Effectful.Dispatch.Dynamic
@ -30,40 +32,22 @@ import Effects.Time
import UnliftIO.Exception (bracket_) import UnliftIO.Exception (bracket_)
import UnliftIO.IO (stderr) import UnliftIO.IO (stderr)
import Prelude hiding (log) import Prelude hiding (log)
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as LB
import Terminal import Terminal
class LogData a where newtype LogData = LogData T.Builder
toLog :: a -> T.Builder deriving newtype (IsString)
deriving newtype (Semigroup)
instance LogData T.Builder where deriving newtype (Monoid)
toLog = id
instance LogData Text where
toLog = T.fromText
instance LogData LT.Text where
toLog = T.fromLazyText
instance LogData String where
toLog = T.fromString
instance LogData B.ByteString where
toLog = toLog . T.decodeUtf8With T.lenientDecode
instance LogData LB.ByteString where
toLog = toLog . LT.decodeUtf8With T.lenientDecode
data Log :: Effect where data Log :: Effect where
Log :: Severity -> T.Builder -> Log m () Log :: Severity -> LogData -> Log m ()
makeEffect ''Log makeEffect ''Log
runLog :: runLog ::
(Time :> es, Concurrent :> es, IOE :> es) => (Time :> es, Concurrent :> es, IOE :> es) =>
LogAction IO T.Builder -> LogAction IO LogData ->
Eff (Log : es) a -> Eff (Log : es) a ->
Eff es a Eff es a
runLog logger e = do runLog logger e = do
@ -73,7 +57,7 @@ runLog logger e = do
runLogWithQsem :: runLogWithQsem ::
(Time :> es, Concurrent :> es, IOE :> es) => (Time :> es, Concurrent :> es, IOE :> es) =>
QSem -> QSem ->
LogAction IO T.Builder -> LogAction IO LogData ->
Eff (Log : es) a -> Eff (Log : es) a ->
Eff es a Eff es a
runLogWithQsem lock logger e = do runLogWithQsem lock logger e = do
@ -83,29 +67,39 @@ runLogWithQsem lock logger e = do
Log sev msg -> do Log sev msg -> do
lock' <- ask lock' <- ask
bracket_ (waitQSem lock') (signalQSem lock') $ do bracket_ (waitQSem lock') (signalQSem lock') $ do
t <- currentTimeB t <- LogData <$> currentTimeB
liftIO $ cmap (addTime t . fmtMessage) logger <& msg `WithSeverity` sev liftIO $ cmap (addTime t . fmtMessage) logger <& msg `WithSeverity` sev
) )
e e
stderrLogger :: stderrLogger ::
(MonadIO m) => (MonadIO m) =>
LogAction m T.Builder LogAction m LogData
stderrLogger = LogAction (liftIO . T.hPutStrLn stderr . LT.toStrict . T.toLazyText) stderrLogger =
LogAction
( \(LogData d) ->
liftIO . T.hPutStrLn stderr . LT.toStrict . T.toLazyText $ d
)
fmtMessage :: WithSeverity T.Builder -> T.Builder fmtMessage :: WithSeverity LogData -> LogData
fmtMessage (WithSeverity txt sev) = "[" <> T.fromText (justifyLeft 7 ' ' (colorSev sev)) <> "] - " <> txt fmtMessage (WithSeverity txt sev) = "[" <> ls (justifyLeft 7 ' ' (colorSev sev)) <> "] - " <> txt
where where
colorSev :: Severity -> Text colorSev :: Severity -> Text
colorSev W = colorNormal Red . tshow $ W colorSev W = colorNormal Red . tshow $ W
colorSev a = tshow a colorSev a = tshow a
addTime :: addTime ::
T.Builder -> LogData ->
T.Builder -> LogData ->
T.Builder LogData
addTime t msg = (" [" :: T.Builder) <> t <> ("] " :: T.Builder) <> toLog msg addTime t msg = " [" <> t <> "] " <> msg
--- Helpers --- Helpers
tshow :: Show a => a -> Text tshow :: (Show a) => a -> Text
tshow = T.pack . show tshow = T.pack . show
logStr :: (StringConv a Text) => a -> LogData
logStr t = LogData (T.fromText $ toS t)
ls :: (StringConv a Text) => a -> LogData
ls = logStr