@hackage monad-effect-logging0.3.0.0
A flexible logging system utilizing the `monad-effect` effect system.
Categories
License
BSD-3-Clause
Maintainer
eikochanowo@outlook.com
Links
Versions
Installation
Dependencies (14)
- aeson <2.3
- base >=4 && <5
- bytestring <0.13
- clock <0.9
- fast-logger >=3 && <3.3
- lens <5.4 Show all…
Dependents (0)
Flexible Logging with Monad-Effect
monad-effect-logging is a pure structured logging library for the monad-effect ecosystem.
The current API is centered on one unified message payload LogDoc.
Highlights
-
You build one
LogDocvalue and decide at the boundary how to render it:- plain text
- ANSI colored text
- different
Showstrategies - custom logger pipelines
-
Color stays semantic until rendering time. A file logger can ignore color while a console logger can emit ANSI codes from the exact same log event.
-
Excellent
TraceIdsupport -
Open log categories, extensible
-
Easy JSON logging by tagging
loggerJson
This enables you to easily add JSON logging to your files while keeping the console output colorful and readable: you can write no-color json logging to a file while use pSho and color constructors to display stuff on the screen at the same time.
Core types
LogEventfor the event envelopeLogWithSourceMetafor source-location metadataLogDocfor the structured log messageLoggerfor the sinkLogEffectfor the installed effect
data LogEvent a = LogEvent
{ logEventCats :: [LogCat]
, logEventPayload :: a
}
data LogWithSourceMeta a = LogWithSourceMeta
{ logMetaLoc :: Maybe Loc
, logMetaSource :: Maybe LogSource
, logMetaDoc :: a
}
newtype Logger m a = Logger
{ runLogger :: LogEvent a -> m ()
}
data LogEffect m a
data LogDoc
The default installed logging effect is:
type Logging = LogEffect IO LogDoc
Building messages
String literals work through IsString, and deferred values use logShow.
import Module.Logging
example :: (Monad m, In (LogEffect m LogDoc) mods) => EffT mods es m ()
example = do
$(logTH Info) $ "starting request " <> logShow (42 :: Int)
$(logTH Warn) $ logFg Yellow "slow query: " <> toLog ("SELECT ..." :: String)
Useful helpers:
logRawlogShowlogFglogBglogBoldtoLog
Literal strings can be directly typed in using IsString class, no need to convert using helpers.
Rendering and base loggers
Most applications should use one options-based helper from Module.Logging.Logger:
import Module.Logging
import Module.Logging.Logger
runApp :: EffT '[LogEffect IO LogDoc] NoError IO () -> IO ()
runApp app = do
stdoutBase <- createSimpleConcurrentStdoutBaseLogger
fileBase <- createFileLogger "app.log"
let stdoutLogger = makeLoggerFromBase ( buildLoggerStyle loggerUseAnsi ) stdoutBase
let fileLogger = makeLoggerFromBase ( buildLoggerStyle (loggerJson . loggerNoStyle) ) fileBase
runEffT00 $ withLoggerCleanup (stdoutLogger <> fileLogger) app
Here each style is a builder function LoggerOptions -> LoggerOptions, and the buildLoggerStyle function is just a composition of them on the defaultLoggerStyle.
For custom pipelines, use the lower-level building blocks:
renderLogEventloggerFromRenderer- your own
Logger
Styles compose as normal functions:
verboseConsole :: LoggerOptions
verboseConsole =
buildLoggerStyle
$ loggerUseAnsi
. loggerOrder [LogTimeChunk, LogCatChunk, LogLocChunk, LogDocChunk]
Categories
Categories are open and extensible:
data ProxyLog = Bytes | Logic deriving (Lift)
-- The `Lift` class is only necessary if you want to use them inside `logTH` template haskell
-- utilities, otherwise you can remove it.
instance IsLogCat ProxyLog where
severity Bytes = severity Debug
severity Logic = severity Info
logTypeName Bytes = "BYTES"
logTypeName Logic = "LOGIC"
You can add local categories with effAddLogCat, and filter them with the existing combinators.
MonadLogger compatibility
MonadLogger and MonadLoggerIO are implemented for LogEffect m LogDoc.
Incoming monad-logger messages are wrapped as logRaw, so compatibility fits directly into the unified payload model.
TraceId
This library also provides a super convenient TraceId mechanism that can attach scoped trace IDs to log events.
TraceId is just a log category. Use withTraceId or one of the provided generators from Module.Logging.TraceId.
Status
This release presents the library around LogDoc, options-based logger construction, open categories, and boundary-driven rendering.