module GHC.Eventlog.Live.Internal.Logger (
LogSource,
logMessage,
logError,
logWarning,
logInfo,
logDebug,
) where
import Control.Exception (bracket_)
import Control.Monad.IO.Class (MonadIO (..))
import Data.Text (Text)
import Data.Text qualified as T
import Data.Text.IO qualified as TIO
import GHC.Eventlog.Live.Verbosity (Verbosity, showVerbosity, verbosityDebug, verbosityError, verbosityInfo, verbosityWarning)
import System.Console.ANSI (Color (..), ColorIntensity (..), ConsoleLayer (..), SGR (..), hNowSupportsANSI, hSetSGR)
import System.IO qualified as IO
type LogSource = Text
logMessage :: (MonadIO m) => IO.Handle -> Verbosity -> Verbosity -> LogSource -> Text -> m ()
logMessage :: forall (m :: * -> *).
MonadIO m =>
Handle -> Verbosity -> Verbosity -> Text -> Text -> m ()
logMessage Handle
handle Verbosity
verbosityLevel Verbosity
verbosityThreshold Text
logSource Text
msg
| Verbosity
verbosityLevel Verbosity -> Verbosity -> Bool
forall a. Ord a => a -> a -> Bool
>= Verbosity
verbosityThreshold = IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ do
Verbosity -> Handle -> (Handle -> IO ()) -> IO ()
forall a. Verbosity -> Handle -> (Handle -> IO a) -> IO a
withVerbosityColor Verbosity
verbosityLevel Handle
handle
((Handle -> IO ()) -> IO ())
-> (Text -> Handle -> IO ()) -> Text -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Handle -> Text -> IO ()) -> Text -> Handle -> IO ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip Handle -> Text -> IO ()
TIO.hPutStrLn
(Text -> Handle -> IO ())
-> (Text -> Text) -> Text -> Handle -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Verbosity -> Verbosity -> Text -> Text -> Text
formatMessage Verbosity
verbosityLevel Verbosity
verbosityThreshold Text
logSource
(Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ Text
msg
Handle -> IO ()
IO.hFlush Handle
handle
| Bool
otherwise = () -> m ()
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
formatMessage :: Verbosity -> Verbosity -> LogSource -> Text -> Text
formatMessage :: Verbosity -> Verbosity -> Text -> Text -> Text
formatMessage Verbosity
verbosityLevel Verbosity
verbosityThreshold Text
logSource Text
msg
| Verbosity
verbosityLevel Verbosity -> Verbosity -> Bool
forall a. Eq a => a -> a -> Bool
== Verbosity
verbosityInfo Bool -> Bool -> Bool
&& Verbosity
verbosityThreshold Verbosity -> Verbosity -> Bool
forall a. Eq a => a -> a -> Bool
/= Verbosity
verbosityDebug = Text
msg
| Bool
otherwise = [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat [Verbosity -> Text
showVerbosity Verbosity
verbosityLevel, String -> Text
T.pack String
"[", Text
logSource, String -> Text
T.pack String
"]: ", Text
msg]
withVerbosityColor :: Verbosity -> IO.Handle -> (IO.Handle -> IO a) -> IO a
withVerbosityColor :: forall a. Verbosity -> Handle -> (Handle -> IO a) -> IO a
withVerbosityColor Verbosity
verbosity Handle
handle Handle -> IO a
action = do
Bool
supportsANSI <- Handle -> IO Bool
hNowSupportsANSI Handle
handle
if Bool -> Bool
not Bool
supportsANSI
then
Handle -> IO a
action Handle
handle
else case Verbosity -> Maybe Color
verbosityColor Verbosity
verbosity of
Maybe Color
Nothing ->
Handle -> IO a
action Handle
handle
Just Color
color -> do
let setVerbosityColor :: IO ()
setVerbosityColor = Handle -> [SGR] -> IO ()
hSetSGR Handle
handle [ConsoleLayer -> ColorIntensity -> Color -> SGR
SetColor ConsoleLayer
Foreground ColorIntensity
Vivid Color
color]
let setDefaultColor :: IO ()
setDefaultColor = Handle -> [SGR] -> IO ()
hSetSGR Handle
handle [ConsoleLayer -> SGR
SetDefaultColor ConsoleLayer
Foreground]
IO () -> IO () -> IO a -> IO a
forall a b c. IO a -> IO b -> IO c -> IO c
bracket_ IO ()
setVerbosityColor IO ()
setDefaultColor (IO a -> IO a) -> IO a -> IO a
forall a b. (a -> b) -> a -> b
$ Handle -> IO a
action Handle
handle
verbosityColor :: Verbosity -> Maybe Color
verbosityColor :: Verbosity -> Maybe Color
verbosityColor Verbosity
verbosity
| Verbosity
verbosity Verbosity -> Verbosity -> Bool
forall a. Eq a => a -> a -> Bool
== Verbosity
verbosityError = Color -> Maybe Color
forall a. a -> Maybe a
Just Color
Red
| Verbosity
verbosity Verbosity -> Verbosity -> Bool
forall a. Eq a => a -> a -> Bool
== Verbosity
verbosityWarning = Color -> Maybe Color
forall a. a -> Maybe a
Just Color
Yellow
| Verbosity
verbosity Verbosity -> Verbosity -> Bool
forall a. Eq a => a -> a -> Bool
== Verbosity
verbosityDebug = Color -> Maybe Color
forall a. a -> Maybe a
Just Color
Blue
| Bool
otherwise = Maybe Color
forall a. Maybe a
Nothing
logError :: (MonadIO m) => Verbosity -> LogSource -> Text -> m ()
logError :: forall (m :: * -> *).
MonadIO m =>
Verbosity -> Text -> Text -> m ()
logError = Handle -> Verbosity -> Verbosity -> Text -> Text -> m ()
forall (m :: * -> *).
MonadIO m =>
Handle -> Verbosity -> Verbosity -> Text -> Text -> m ()
logMessage Handle
IO.stderr Verbosity
verbosityError
logWarning :: (MonadIO m) => Verbosity -> LogSource -> Text -> m ()
logWarning :: forall (m :: * -> *).
MonadIO m =>
Verbosity -> Text -> Text -> m ()
logWarning = Handle -> Verbosity -> Verbosity -> Text -> Text -> m ()
forall (m :: * -> *).
MonadIO m =>
Handle -> Verbosity -> Verbosity -> Text -> Text -> m ()
logMessage Handle
IO.stderr Verbosity
verbosityWarning
logInfo :: (MonadIO m) => Verbosity -> LogSource -> Text -> m ()
logInfo :: forall (m :: * -> *).
MonadIO m =>
Verbosity -> Text -> Text -> m ()
logInfo = Handle -> Verbosity -> Verbosity -> Text -> Text -> m ()
forall (m :: * -> *).
MonadIO m =>
Handle -> Verbosity -> Verbosity -> Text -> Text -> m ()
logMessage Handle
IO.stdout Verbosity
verbosityInfo
logDebug :: (MonadIO m) => Verbosity -> LogSource -> Text -> m ()
logDebug :: forall (m :: * -> *).
MonadIO m =>
Verbosity -> Text -> Text -> m ()
logDebug = Handle -> Verbosity -> Verbosity -> Text -> Text -> m ()
forall (m :: * -> *).
MonadIO m =>
Handle -> Verbosity -> Verbosity -> Text -> Text -> m ()
logMessage Handle
IO.stderr Verbosity
verbosityDebug