# Easy Logging for Haskell
Easy-logger can be used to easily create logs, without handling any Monad. Just log as you go. The
package provides logging for code that lives in the `IO` Monad, implements `MonadIO m`, as well as
for pure code.
## Usage
Initialise the logger for your package and start logging:
{-# LANGUAGE TemplateHaskell #-}
import EasyLogger
import qualified Data.Text as T
main :: IO ()
main = do
$(initLogger) (LogFile "package.log") LogDebug
$(logInfo) ("Starting App" :: T.Text)
...
# At the end of your program, flush the buffers:
finalizeAllLoggers
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 ()
main = do
$(initLoggerAllPackages) (LogFile "package.log") LogAll True
$(logInfo) ("Starting App" :: T.Text)
...
# At the end of your program, flush the buffers:
finalizeAllLoggers
You want to log in pure code without wrapping anything in a Monad? Here you go:
fromEither :: Either String Int -> Int
fromEither (Right v) = v
fromEither (Left str) = $(pureLogPrintError) ("Parse error: " <> T.pack str) defaultValue
defaultValue = 0
Under the hood `pureLogPrintError` uses `unsafePerformIO` to log. The return value, i.e.
`defaultValue` in the example, ensures that the log is actually executed when the error occurs.
## Log Levels and Destinations
The available log levels are:
-- | Log Level. Levels are sorted. `All` < `Debug` < `Info` < `Warning` < `Error`.
-- None disables all logging. Default: All
data LogLevel
= LogNone
| LogAll
| LogDebug
| LogInfo
| LogWarning
| LogError
deriving (Show, Read, Bounded, Enum, Eq, Ord)
The logger can be used to log to `stderr`, `stdout` or a file:
-- | Logging destination. See also `setLoggingDestination`.
data LogDestination
= LogStdErr
| LogStdOut
| LogFile FilePath
## Library
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 #-}
module My.Great.Package.Logging
( enableMyGreatPackageLogging
, disableMyGreatPackageLogging
) where
import EasyLogger
enableMyGreatPackageLogging :: LogDestination -> LogLevel -> IO ()
enableMyGreatPackageLogging = $(initLogger)
disableMyGreatPackageLogging :: IO ()
disableMyGreatPackageLogging = $(finalizeLogger)