packages feed

easy-logger 0.1.0.4 → 0.1.0.6

raw patch · 4 files changed

+230/−49 lines, 4 filesPVP: minor bump suggested

API additions: PVP suggests at least a minor version bump

API changes (from Hackage documentation)

+ EasyLogger.LogStr: fromLogStr :: LogStr -> ByteString
+ EasyLogger.Logger: logAllText :: Q Exp
+ EasyLogger.Logger: logDebugText :: Q Exp
+ EasyLogger.Logger: logErrorText :: Q Exp
+ EasyLogger.Logger: logInfoText :: Q Exp
+ EasyLogger.Logger: logPrintAllText :: Q Exp
+ EasyLogger.Logger: logPrintDebugText :: Q Exp
+ EasyLogger.Logger: logPrintErrorText :: Q Exp
+ EasyLogger.Logger: logPrintInfoText :: Q Exp
+ EasyLogger.Logger: logPrintWarningText :: Q Exp
+ EasyLogger.Logger: logWarningText :: Q Exp
+ EasyLogger.Logger: pureLogAllText :: Q Exp
+ EasyLogger.Logger: pureLogDebugText :: Q Exp
+ EasyLogger.Logger: pureLogErrorText :: Q Exp
+ EasyLogger.Logger: pureLogInfoText :: Q Exp
+ EasyLogger.Logger: pureLogPrintAllText :: Q Exp
+ EasyLogger.Logger: pureLogPrintDebugText :: Q Exp
+ EasyLogger.Logger: pureLogPrintErrorText :: Q Exp
+ EasyLogger.Logger: pureLogPrintInfoText :: Q Exp
+ EasyLogger.Logger: pureLogPrintWarningText :: Q Exp
+ EasyLogger.Logger: pureLogWarningText :: Q Exp
+ EasyLogger.Logger: setPrintLocationToConsole :: Bool -> IO ()

Files

README.md view
@@ -8,7 +8,9 @@  Initialise the logger for your package and start logging: -    import qualified Data.Text                          as T+    {-# LANGUAGE TemplateHaskell     #-}+    import           EasyLogger+    import qualified Data.Text  as T      main :: IO ()     main = do@@ -18,11 +20,50 @@       # At the end of your program, flush the buffers:       finalizeAllLoggers -You can also include the logs of the libraries that you use and which use the `easy-logger` package-for logging. If the library maintainer is nice, (s)he allows you to turn on/off logging for that-library only. See the Library section below how to do it. To turn logging for all packages-(that use easy-logger) on, do this:+The log output looks like this: +    $ cat package.log+    [INFO #22-Oct-2021 12:27:23] Starting App                           @(main:Main+++If you use libraries, **including your own package library**, to log from a file outside of+`Main.hs` you need to make the library package name available and enable the logging specifically. For this create following file:++    {-# LANGUAGE TemplateHaskell #-}+    module MyPackage.Logging+        ( enableMyPackageLogging+        , disableMyPackageLogging+        ) where++    import           EasyLogger++    enableMyPackageLogging :: LogDestination -> LogLevel -> IO ()+    enableMyPackageLogging = $(initLogger)++    disableMyPackageLogging :: IO ()+    disableMyPackageLogging = $(finalizeLogger)++and then enable it:++    {-# LANGUAGE TemplateHaskell     #-}+    import           EasyLogger+    import           MyPackage.Logging+    import qualified Data.Text  as T++    main :: IO ()+    main = do+      $(initLogger) (LogFile "package.log") LogDebug+      enableMyPackageLogging (LogFile "package.log") LogDebug+      ...+      # At the end of your program, flush the buffers:+      finalizeAllLoggers+++You can also include the logs of all the libraries that you use and which use the `easy-logger`+package for logging:++    {-# LANGUAGE TemplateHaskell     #-}+    import           EasyLogger     import qualified Data.Text                          as T      main :: IO ()@@ -47,7 +88,8 @@  The available log levels are: -    -- | Log Level. Levels are sorted. `All` < `Debug` < `Info` < `Warning` < `Error`. None disables all logging. Default: All+    -- | Log Level. Levels are sorted. `All` < `Debug` < `Info` < `Warning` < `Error`.+    --   None disables all logging. Default: All     data LogLevel       = LogNone       | LogAll@@ -68,8 +110,9 @@  ## Library -If you are exposing a library, let your user turn on/off the logging for your library. The-Template-Haskell code ensures that your package name is provided to the logger, and thus logging for this module only is turned on/off.+If you are exposing a library (including your own library), let your user turn on/off the logging+for your library. The Template-Haskell code ensures that your package name is provided to the+logger, and thus logging for this module only is turned on/off.       {-# LANGUAGE TemplateHaskell #-}
easy-logger.cabal view
@@ -5,9 +5,9 @@ -- see: https://github.com/sol/hpack  name:           easy-logger-version:        0.1.0.4+version:        0.1.0.6 synopsis:       Logging made easy.-description:    Please see the README on GitHub at <https://github.com/githubuser/easy-logger#readme>+description:    Please see the README on GitHub at <https://github.com/schnecki/easy-logger#readme> category:       Logging homepage:       https://github.com/schnecki/easy-logger#readme bug-reports:    https://github.com/schnecki/easy-logger/issues
src/EasyLogger/LogStr.hs view
@@ -1,10 +1,10 @@-{-# LANGUAGE FlexibleInstances    #-}-{-# LANGUAGE OverloadedStrings    #-}-{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE OverloadedStrings #-} module EasyLogger.LogStr     ( LogStr (..)     , ToLogStr (..)     , logStrLen+    , fromLogStr     , mkMinLogStrLen     ) where 
src/EasyLogger/Logger.hs view
@@ -7,6 +7,7 @@     , initLoggerAllPackages     , setLoggingDestination     , setMinLogLevel+    , setPrintLocationToConsole     , logAll     , logPrintAll     , logDebug@@ -27,6 +28,26 @@     , pureLogPrintWarning     , pureLogError     , pureLogPrintError+    , logAllText+    , logPrintAllText+    , logDebugText+    , logPrintDebugText+    , logInfoText+    , logPrintInfoText+    , logWarningText+    , logPrintWarningText+    , logErrorText+    , logPrintErrorText+    , pureLogAllText+    , pureLogPrintAllText+    , pureLogDebugText+    , pureLogPrintDebugText+    , pureLogInfoText+    , pureLogPrintInfoText+    , pureLogWarningText+    , pureLogPrintWarningText+    , pureLogErrorText+    , pureLogPrintErrorText     , finalizeAllLoggers     , finalizeLogger     , flushLoggers@@ -51,8 +72,6 @@ import           EasyLogger.Util            (liftLoc)  -import           Debug.Trace- -- | Add a @LoggerSet@ to the known loggers. setLoggerSet :: String -> LoggerSet -> IO () setLoggerSet pkgName set = modifyIORef' loggerSets (M.insert pkgName set)@@ -117,11 +136,11 @@ -- | Initialise the logger. MUST only be called in the executable code (not the exposed library code)! Takes a `Bool` that decides wether to log messages from other packages that use the same library -- and did not initalize the Logger (which should be the case for all of them!). initLoggerAllPackages :: Q Exp-initLoggerAllPackages = [| \dest logLevel logAllPkgs -> setMinLogLevel logLevel >> setLoggingDestination (loc_package $(qLocation >>= liftLoc)) dest logAllPkgs |]+initLoggerAllPackages = [| \dest logAllPkgs -> setLoggingDestination (loc_package $(qLocation >>= liftLoc)) dest logAllPkgs |]  -- | Initialise the logger. MUST only be called in the executable code (not the exposed library code)! Ignores the other packages logs, if the same packages is used for logging. initLogger :: Q Exp-initLogger = [| \dest logLevel -> setMinLogLevel logLevel >> setLoggingDestination (loc_package $(qLocation >>= liftLoc)) dest False |]+initLogger = [| \dest -> setLoggingDestination (loc_package $(qLocation >>= liftLoc)) dest False |]  -- | Set the destination for all consequitive for logging. You should only set this once, at the beginning of the program! The default is `LogStdOut`. setLoggingDestination :: String -> LogDestination -> LogFromAllPackages -> IO ()@@ -174,10 +193,10 @@ logLevelText LogError   = "ERROR"  -- | Generic log function. Use TH version, e.g. `logDebug`.-logFun :: (ToLogStr msg) => Loc -> LogLevel -> msg -> IO ()-logFun _ LogNone _ = return ()-logFun loc@(Loc _ pkg _ _ _) level msg = do-  minLevel <- readIORef minLogLevel+logFun :: (ToLogStr msg) => Bool -> Loc -> LogLevel -> msg -> IO ()+logFun _ _ LogNone _ = return ()+logFun printMsg loc@(Loc _ pkg _ _ _) level msg = do+  (minLevel, printLoc) <- readIORef minLogLevel   when (level >= minLevel) $ do     now <- join (readIORef cachedTime)     readIORef loggerSets >>= \sets ->@@ -185,167 +204,286 @@         Nothing -- Check the package name of the caller, as otherwise any library logging would halt the process.           | M.null sets && pkg == mainLogPkgName -> error "You must call `initLogger` at the start of your application! See the documentation of `EasyLogger.Logger`."         Nothing -> return ()-        Just set -> pushLogStr set (defaultLogStr loc now level (toLogStr msg))+        Just set -> do+          let logStr = defaultLogStr True loc now level (toLogStr msg)+              logStrPrint | printLoc = logStr+                          | otherwise = defaultLogStr False loc now level (toLogStr msg)+          when printMsg $ S8.hPutStr handle (fromLogStr logStrPrint) >> hFlush handle+          pushLogStr set logStr   where     getLogger sets = M.lookup pkg sets <|> M.lookup defaultLogPkgName sets+    handle = case level of+      LogError -> stderr+      _        -> stdout  +mkTxt :: T.Text -> T.Text+mkTxt = id++ cachedTime :: IORef (IO FormattedTime) cachedTime = unsafePerformIO $ do   cache <- newTimeCache simpleTimeFormat'   newIORef cache -minLogLevel :: IORef LogLevel-minLogLevel = unsafePerformIO $ newIORef LogAll+-- | Min Log Level and whether to print location to console.+minLogLevel :: IORef (LogLevel, Bool)+minLogLevel = unsafePerformIO $ newIORef (LogAll, False) {-# NOINLINE minLogLevel  #-}  -- | Set the least logging level. Levels lower will not be logged. Log Level Order: `Debug` < `Info` < `Warning` < `Error`. `None` disables all logging. Note that the output to stderr using e.g. `logPrintError` will not -- be affected! setMinLogLevel :: LogLevel -> IO ()-setMinLogLevel = writeIORef minLogLevel+setMinLogLevel x = modifyIORef minLogLevel (\(_, b) -> (x, b)) +-- | Set the least logging level. Levels lower will not be logged. Log Level Order: `Debug` < `Info` < `Warning` < `Error`. `None` disables all logging. Note that the output to stderr using e.g. `logPrintError` will not+-- be affected!+setPrintLocationToConsole :: Bool -> IO ()+setPrintLocationToConsole x = modifyIORef minLogLevel (\(l, _) -> (l, x))++ ------------------------------ All ------------------------------  -- | Generates a function that takes a 'Text' and logs a 'LevelAll' message. Usage: ----- > $(logAll) "This is a debug log message"+-- > $(logAll) ("This is a debug log message" :: T.Text) logAll :: Q Exp-logAll = [| liftIO . logFun $(qLocation >>= liftLoc) LogAll |]+logAll = [| liftIO . logFun False $(qLocation >>= liftLoc) LogAll |] +-- | Same as logAll, but with concrete type `Text` as message.+--+-- > $(logAll) "This is a debug log message"+--+logAllText :: Q Exp+logAllText = [| liftIO . logFun False $(qLocation >>= liftLoc) LogAll . mkTxt |]++ -- | Same as `logAll`, but for pure code. Uses @unsafePerformIO@. -- -- > $(pureLogAll) "This is a debug log message" (3 * 3) pureLogAll :: Q Exp-pureLogAll = [| \txt a -> unsafePerformIO (logFun $(qLocation >>= liftLoc) LogAll txt >> return a) |]+pureLogAll = [| \txt a -> unsafePerformIO (logFun False $(qLocation >>= liftLoc) LogAll txt >> return a) |] +-- | Same as `pureLogAll`, but with concrete type `Text` as message.+pureLogAllText :: Q Exp+pureLogAllText = [| \txt a -> unsafePerformIO (logFun False $(qLocation >>= liftLoc) LogAll (mkTxt txt) >> return a) |] + -- | Same as `logAll`, but also prints the message on `stdout`. logPrintAll :: Q Exp-logPrintAll = [| \txt -> liftIO (hPutStrLn stdout ("DEBUG: " ++ T.unpack txt) >> hFlush stdout >> logFun $(qLocation >>= liftLoc) LogAll txt) |]+logPrintAll = [| liftIO . logFun True $(qLocation >>= liftLoc) LogAll |] +-- | Same as `logAll`, but also prints the message on `stdout`. Only for `Text`.+logPrintAllText :: Q Exp+logPrintAllText = [| liftIO . logFun True $(qLocation >>= liftLoc) LogAll . mkTxt |]++ -- | Same as `pureLogAll`, but also prints the message on `stdout`. -- -- > $(pureLogPrintAll) "This is a debug log message" (3 * 3) pureLogPrintAll :: Q Exp-pureLogPrintAll = [| \txt a -> unsafePerformIO (hPutStrLn stdout ("DEBUG: " ++ T.unpack txt) >> hFlush stdout >> logFun $(qLocation >>= liftLoc) LogAll txt >> return a) |]+pureLogPrintAll = [| \txt a -> unsafePerformIO (logFun True $(qLocation >>= liftLoc) LogAll txt >> return a) |]  +-- | Same as `pureLogPrintAll`, but with concrete type `Text` as log message.+pureLogPrintAllText :: Q Exp+pureLogPrintAllText = [| \txt a -> unsafePerformIO (logFun True $(qLocation >>= liftLoc) LogAll (mkTxt txt) >> return a) |]++ ------------------------------ Debug ------------------------------  -- | Generates a function that takes a 'Text' and logs a 'LevelDebug' message. Usage: -- -- > $(logDebug) "This is a debug log message" logDebug :: Q Exp-logDebug = [| liftIO . logFun $(qLocation >>= liftLoc) LogDebug |]+logDebug = [| liftIO . logFun False $(qLocation >>= liftLoc) LogDebug |] +-- | Same as `logDebug` but with `Text` as fixed message type.+logDebugText :: Q Exp+logDebugText = [| liftIO . logFun False $(qLocation >>= liftLoc) LogDebug . mkTxt |]++ -- | Same as `logDebug`, but for pure code. Uses @unsafePerformIO@ -- -- > $(pureLogDebug) "This is a debug log message" defaultValue pureLogDebug :: Q Exp-pureLogDebug = [| \txt a -> unsafePerformIO (logFun $(qLocation >>= liftLoc) LogDebug txt >> return a) |]+pureLogDebug = [| \txt a -> unsafePerformIO (logFun False $(qLocation >>= liftLoc) LogDebug txt >> return a) |]  +-- | Same as `pureLogDebug`, but with concrete type `Text` as message.+pureLogDebugText :: Q Exp+pureLogDebugText = [| \txt a -> unsafePerformIO (logFun False $(qLocation >>= liftLoc) LogDebug (mkTxt txt) >> return a) |]++ -- | Same as `logDebug`, but also prints the message on `stdout`. logPrintDebug :: Q Exp-logPrintDebug = [| \txt -> hPutStrLn stdout ("DEBUG: " ++ T.unpack txt) >> hFlush stdout >> logFun $(qLocation >>= liftLoc) LogDebug txt |]+logPrintDebug = [| liftIO . logFun True $(qLocation >>= liftLoc) LogDebug |] +-- | Same as `logDebug`, but also prints the message on `stdout`. Only for Text.+logPrintDebugText :: Q Exp+logPrintDebugText = [| liftIO . logFun True $(qLocation >>= liftLoc) LogDebug . mkTxt |]++ -- | Same as `pureLogDebug`, but also prints the message on `stdout`. -- -- > $(purePrintLogDebug) "This is a debug log message" defaultValue pureLogPrintDebug :: Q Exp-pureLogPrintDebug = [| \txt a -> unsafePerformIO (hPutStrLn stdout ("DEBUG: " ++ T.unpack txt) >> hFlush stdout >> logFun $(qLocation >>= liftLoc) LogDebug txt >> return a) |]+pureLogPrintDebug = [| \txt a -> unsafePerformIO (logFun True $(qLocation >>= liftLoc) LogDebug txt >> return a) |]  +-- | Same as `pureLogPrintDebug`, but with concrete type `Text` as log message.+pureLogPrintDebugText :: Q Exp+pureLogPrintDebugText = [| \txt a -> unsafePerformIO (logFun True $(qLocation >>= liftLoc) LogDebug (mkTxt txt) >> return a) |]++ ------------------------------ Info ------------------------------  -- | Generates a function that takes a 'Text' and logs a 'LevelInfo' message. Usage: -- -- > $(logInfo) "This is a info log message" logInfo :: Q Exp-logInfo = [| liftIO . logFun $(qLocation >>= liftLoc) LogInfo |]+logInfo = [| liftIO . logFun False $(qLocation >>= liftLoc) LogInfo |] ++-- | Same as `logInfo` but with `Text` as fixed message type.+logInfoText :: Q Exp+logInfoText = [| liftIO . logFun False $(qLocation >>= liftLoc) LogInfo . mkTxt |]++ -- | Same as `logInfo`, but for pure code. Uses @unsafePerformIO@. -- -- > $(pureLogInfo) "This is a warning log message" (funcX 10) pureLogInfo :: Q Exp-pureLogInfo = [| \txt a -> unsafePerformIO (logFun $(qLocation >>= liftLoc) LogInfo txt >> return a) |]+pureLogInfo = [| \txt a -> unsafePerformIO (logFun False $(qLocation >>= liftLoc) LogInfo txt >> return a) |]  +-- | Same as `pureLogInfo`, but with concrete type `Text` as message.+pureLogInfoText :: Q Exp+pureLogInfoText = [| \txt a -> unsafePerformIO (logFun False $(qLocation >>= liftLoc) LogInfo (mkTxt txt) >> return a) |]++ -- | Same as `logInfo`, but also prints the message on `stdout`. logPrintInfo :: Q Exp-logPrintInfo = [| \txt -> liftIO (hPutStrLn stdout ("INFO: " ++ T.unpack txt) >> hFlush stdout >> logFun $(qLocation >>= liftLoc) LogInfo txt) |]+logPrintInfo = [| liftIO . logFun True $(qLocation >>= liftLoc) LogInfo |] +-- | Same as `logInfo`, but also prints the message on `stdout`.+logPrintInfoText :: Q Exp+logPrintInfoText = [| liftIO . logFun True $(qLocation >>= liftLoc) LogInfo . mkTxt |]++ -- | Same as `pureLogInfo`, but also prints the message on `stdout`. -- -- > $(pureLogPrintInfo) "This is a warning log message" (funcX 10) pureLogPrintInfo :: Q Exp-pureLogPrintInfo = [| \txt a -> unsafePerformIO (hPutStrLn stdout ("INFO: " ++ T.unpack txt) >> hFlush stdout >> logFun $(qLocation >>= liftLoc) LogInfo txt >> return a) |]+pureLogPrintInfo = [| \txt a -> unsafePerformIO (logFun True $(qLocation >>= liftLoc) LogInfo txt >> return a) |]  +-- | Same as `pureLogPrintInfo`, but with concrete type `Text` as log message.+pureLogPrintInfoText :: Q Exp+pureLogPrintInfoText = [| \txt a -> unsafePerformIO (logFun True $(qLocation >>= liftLoc) LogInfo (mkTxt txt) >> return a) |]++ ------------------------------ Warning ------------------------------  -- | Generates a function that takes a 'Text' and logs a 'LevelWarning' message. Usage: -- -- > $(logWarning) "This is a warning log message" logWarning :: Q Exp-logWarning = [| liftIO . logFun $(qLocation >>= liftLoc) LogWarning |]+logWarning = [| liftIO . logFun False $(qLocation >>= liftLoc) LogWarning |] +-- | Same as `logWarning` but with `Text` as fixed message type.+logWarningText :: Q Exp+logWarningText = [| liftIO . logFun False $(qLocation >>= liftLoc) LogWarning . mkTxt |]++ -- | Same as `logWarning`, but for pure code. Uses @unsafePerformIO@. -- -- > $(pureLogWarning) "This is a warning log message" "myresult" pureLogWarning :: Q Exp-pureLogWarning = [| \txt a -> unsafePerformIO (logFun $(qLocation >>= liftLoc) LogWarning txt >> return a) |]+pureLogWarning = [| \txt a -> unsafePerformIO (logFun False $(qLocation >>= liftLoc) LogWarning txt >> return a) |] +-- | Same as `pureLogWarning`, but with concrete type `Text` as message.+pureLogWarningText :: Q Exp+pureLogWarningText = [| \txt a -> unsafePerformIO (logFun False $(qLocation >>= liftLoc) LogWarning (mkTxt txt) >> return a) |] + -- | Same as `logWarning`, but also prints the message on `stdout`. logPrintWarning :: Q Exp-logPrintWarning = [| \txt -> liftIO (hPutStrLn stdout ("WARNING: " ++ T.unpack txt) >> hFlush stdout >> logFun $(qLocation >>= liftLoc) LogWarning txt) |]+logPrintWarning = [| liftIO . logFun True $(qLocation >>= liftLoc) LogWarning |]  +-- | Same as `logWarning`, but also prints the message on `stdout`.+logPrintWarningText :: Q Exp+logPrintWarningText = [| liftIO . logFun True $(qLocation >>= liftLoc) LogWarning . mkTxt |]++ -- | Same as `pureLogWarning`, but also prints the warning. -- -- > $(pureLogPrintWarning) "This is a error log message" (4 + 4) pureLogPrintWarning :: Q Exp-pureLogPrintWarning = [| \txt a -> unsafePerformIO (hPutStrLn stdout ("WARNING: " ++ T.unpack txt) >> hFlush stdout >> logFun $(qLocation >>= liftLoc) LogWarning txt >> return a)  |]+pureLogPrintWarning = [| \txt a -> unsafePerformIO (logFun True $(qLocation >>= liftLoc) LogWarning txt >> return a)  |]  +-- | Same as `pureLogPrintWarning`, but with concrete type `Text` as log message.+pureLogPrintWarningText :: Q Exp+pureLogPrintWarningText = [| \txt a -> unsafePerformIO (logFun True $(qLocation >>= liftLoc) LogWarning (mkTxt txt) >> return a) |]++ ------------------------------ Error ------------------------------  -- | Generates a function that takes a 'Text' and logs a 'LevelError' message. Usage: -- -- > $(logError) "This is a error log message" logError :: Q Exp-logError = [| liftIO . logFun $(qLocation >>= liftLoc) LogError |]+logError = [| liftIO . logFun False $(qLocation >>= liftLoc) LogError |] +-- | Same as `logError` but with `Text` as fixed message type.+logErrorText :: Q Exp+logErrorText = [| liftIO . logFun False $(qLocation >>= liftLoc) LogError . mkTxt |]  -- | Same as `logError`, but for pure code. Uses @unsafePerformIO@. -- -- > $(pureLogError) "This is a error log message" (4 + 4) pureLogError :: Q Exp-pureLogError = [| \txt a -> unsafePerformIO (logFun $(qLocation >>= liftLoc) LogError txt >> return a) |]+pureLogError = [| \txt a -> unsafePerformIO (logFun False $(qLocation >>= liftLoc) LogError txt >> return a) |]  +-- | Same as `pureLogError`, but with concrete type `Text` as message.+pureLogErrorText :: Q Exp+pureLogErrorText = [| \txt a -> unsafePerformIO (logFun False $(qLocation >>= liftLoc) LogError (mkTxt txt) >> return a) |]++ -- | Same as `logError`, but also prints the message on `stderr`. logPrintError :: Q Exp-logPrintError = [| \txt -> liftIO (hPutStrLn stderr ("ERROR: " ++ T.unpack txt) >> hFlush stderr >> logFun $(qLocation >>= liftLoc) LogError txt) |]+logPrintError = [| liftIO . logFun True $(qLocation >>= liftLoc) LogError |]  +-- | Same as `logError`, but also prints the message on `stderr`.+logPrintErrorText :: Q Exp+logPrintErrorText = [| liftIO . logFun True $(qLocation >>= liftLoc) LogError . mkTxt |]++ -- | Same as `pureLogError`, but also prints the message on `stderr`. -- -- > $(pureLogPrintError) "This is a error log message" (4 + 4) pureLogPrintError :: Q Exp-pureLogPrintError = [| \txt a -> unsafePerformIO (hPutStrLn stderr ("ERROR: " ++ T.unpack txt) >> hFlush stderr >> logFun $(qLocation >>= liftLoc) LogError txt >> return a) |]+pureLogPrintError = [| \txt a -> unsafePerformIO (logFun True $(qLocation >>= liftLoc) LogError txt >> return a) |] +-- | Same as `pureLogPrintError`, but with concrete type `Text` as log message.+pureLogPrintErrorText :: Q Exp+pureLogPrintErrorText = [| \txt a -> unsafePerformIO (logFun True $(qLocation >>= liftLoc) LogError (mkTxt txt) >> return a) |] + ---- Helpers: -defaultLogStr :: Loc+defaultLogStr :: Bool+              -> Loc               -> FormattedTime               -> LogLevel               -> LogStr               -> LogStr-defaultLogStr loc time level msg =-  "[" <> toLogStr (logLevelText level) <> ("#" <> toLogStr time) <> "] " <> mkTrailWs msg <> " @(" <> toLogStr (S8.pack fileLocStr) <> ")\n"+defaultLogStr prLoc loc time level msg =+  "[" <> toLogStr (logLevelText level) <> ("#" <> toLogStr time) <> "] " <> mkTrailWs msg <> (if prLoc then " @(" <> toLogStr (S8.pack fileLocStr) <> ")\n" else "\n")   where     mkTrailWs = mkMinLogStrLen defaultMinLogMsgLen     fileLocStr = loc_package loc ++ ':' : loc_module loc ++ ' ' : loc_filename loc ++ ':' : line loc ++ ':' : char loc ++ '-' : lineEnd loc ++ ':' : charEnd loc