Safe Haskell | None |
---|---|
Language | Haskell2010 |
Synopsis
- data DataLog a :: Effect where
- interpretDataLogStderrWith :: Member (Embed IO) r => (a -> Text) -> InterpreterFor (DataLog a) r
- interpretDataLogStderr :: Show a => Member (Embed IO) r => InterpreterFor (DataLog a) r
- interpretDataLogStdoutWith :: Member (Embed IO) r => (a -> Text) -> InterpreterFor (DataLog a) r
- interpretDataLogStdout :: Show a => Member (Embed IO) r => InterpreterFor (DataLog a) r
- interpretDataLogAtomic' :: forall a r. Member (AtomicState [a]) r => InterpreterFor (DataLog a) r
- interpretDataLogAtomic :: forall a r. Member (Embed IO) r => InterpretersFor [DataLog a, AtomicState [a]] r
- data LogMessage = LogMessage !Severity !Text
- data LogEntry a = LogEntry !a !UTCTime !CallStack
- data Log :: Effect where
- Log :: HasCallStack => LogMessage -> Log m ()
- log :: HasCallStack => Member Log r => Severity -> Text -> Sem r ()
- trace :: HasCallStack => Member Log r => Text -> Sem r ()
- debug :: HasCallStack => Member Log r => Text -> Sem r ()
- info :: HasCallStack => Member Log r => Text -> Sem r ()
- warn :: HasCallStack => Member Log r => Text -> Sem r ()
- error :: HasCallStack => Member Log r => Text -> Sem r ()
- crit :: HasCallStack => Member Log r => Text -> Sem r ()
- formatLogEntry :: LogEntry LogMessage -> Text
- data Severity
- interpretLogStderrWith :: Members [Embed IO, GhcTime] r => (LogEntry LogMessage -> Text) -> InterpreterFor Log r
- interpretLogStderrConc :: Members [Resource, Async, Race, Embed IO] r => InterpreterFor Log r
- interpretLogStderr :: Members [Embed IO, GhcTime] r => InterpreterFor Log r
- interpretLogStderr' :: Member (Embed IO) r => InterpreterFor Log r
- interpretLogStdoutWith :: Members [Embed IO, GhcTime] r => (LogEntry LogMessage -> Text) -> InterpreterFor Log r
- interpretLogStdoutConc :: Members [Resource, Async, Race, Embed IO] r => InterpreterFor Log r
- interpretLogStdout :: Members [Embed IO, GhcTime] r => InterpreterFor Log r
- interpretLogStdout' :: Member (Embed IO) r => InterpreterFor Log r
- interpretLogDataLog :: Members [DataLog (LogEntry LogMessage), GhcTime] r => InterpreterFor Log r
- interpretLogDataLog' :: Members [DataLog (LogEntry LogMessage), Embed IO] r => InterpretersFor [Log, LogMetadata LogMessage, GhcTime] r
- interpretLogOutput :: Member (Output LogMessage) r => InterpreterFor Log r
- interpretLogNull :: InterpreterFor Log r
- interpretLogAtomic :: Member (Embed IO) r => InterpretersFor [Log, AtomicState [LogMessage]] r
- interpretLogAtomic' :: Member (AtomicState [LogMessage]) r => InterpreterFor Log r
- interceptDataLogConc :: forall msg r a. Members [DataLog msg, Resource, Async, Race, Embed IO] r => Int -> Sem r a -> Sem r a
- interpretLogDataLogConc :: Members [DataLog (LogEntry LogMessage), Resource, Async, Race, Embed IO] r => Int -> InterpreterFor Log r
Introduction
There are at least two libraries that wrap a logging backend with polysemy interpreters. An author of a library who wants to provide log messages faces the problem that committing to a backend requires the user to translate those messages if their chosen backend differs.
polysemy-log provides an abstraction for this task with interpreter adapters for co-log and di.
If you're looking for instructions on how to use polysemy-log with a backend, please visit the haddocks of the adapter libraries:
A program using this library might look like this:
prog :: Member Log r => Sem r () prog = do Log.debug "starting" Log.error "nothing happened"
Arbitrary Data Messages
Logging backends usually don't put any restrictions on the data type that represents a log message, so the adapter effect that faces towards the backend is simply polymorphic in that type.
For complex logging purposes, it would be perfectly valid to use DataLog
directly, even though this library focuses
on simpler messages:
data ComplexMessage = ComplexMessage { points :: Int, user :: Text } prog :: Member (DataLog ComplexMessage) r => Sem r () prog = do dataLog (ComplexMessage 500 "googleson78")
data DataLog a :: Effect where Source #
Adapter for a logging backend.
Usually this is reinterpreted into an effect like those from co-log or di, but it can be used purely for testing.
Instances
type DefiningModule DataLog Source # | |
Defined in Polysemy.Log.Data.DataLog |
Interpreters
interpretDataLogStderrWith :: Member (Embed IO) r => (a -> Text) -> InterpreterFor (DataLog a) r Source #
interpretDataLogStderr :: Show a => Member (Embed IO) r => InterpreterFor (DataLog a) r Source #
interpretDataLogStdoutWith :: Member (Embed IO) r => (a -> Text) -> InterpreterFor (DataLog a) r Source #
interpretDataLogStdout :: Show a => Member (Embed IO) r => InterpreterFor (DataLog a) r Source #
interpretDataLogAtomic' :: forall a r. Member (AtomicState [a]) r => InterpreterFor (DataLog a) r Source #
Interpret DataLog
by prepending each message to a list in an AtomicState
.
interpretDataLogAtomic :: forall a r. Member (Embed IO) r => InterpretersFor [DataLog a, AtomicState [a]] r Source #
Interpret DataLog
by prepending each message to a list in an AtomicState
, then interpret the AtomicState
in a
TVar
.
Text Messages with Severity and Metadata
While it would be quite reasonable to handle any kind of complexly structured logging data ergonomically with polysemy, most authors probably prefer not to burden their users with this task while still appreciating the possibility to easily relay debug information in a standardized way.
The default logging effect uses a simple data structure that annotates the given severity and text message with the source location and timestamp:
data LogMessage Source #
User-specified part of the default logging data, consisting of a severity level like warning, error, debug, and a plain text message.
Instances
Eq LogMessage Source # | |
Defined in Polysemy.Log.Data.LogMessage (==) :: LogMessage -> LogMessage -> Bool # (/=) :: LogMessage -> LogMessage -> Bool # | |
Show LogMessage Source # | |
Defined in Polysemy.Log.Data.LogMessage showsPrec :: Int -> LogMessage -> ShowS # show :: LogMessage -> String # showList :: [LogMessage] -> ShowS # |
Metadata wrapper for a log message.
data Log :: Effect where Source #
The default high-level effect for simple text messages. To be used with the severity constructors:
import qualified Polysemy.Log as Log prog = do Log.debug "debugging…" Log.warn "warning!"
Interpreters should preprocess and relay the message to DataLog
.
Log :: HasCallStack => LogMessage -> Log m () | Schedule a message to be logged. |
log :: HasCallStack => Member Log r => Severity -> Text -> Sem r () Source #
Log a message with the given severity.
Basic Sem
constructor.
trace :: HasCallStack => Member Log r => Text -> Sem r () Source #
Log a message with the Trace
severity.
debug :: HasCallStack => Member Log r => Text -> Sem r () Source #
Log a message with the Debug
severity.
info :: HasCallStack => Member Log r => Text -> Sem r () Source #
Log a message with the Info
severity.
warn :: HasCallStack => Member Log r => Text -> Sem r () Source #
Log a message with the Warn
severity.
error :: HasCallStack => Member Log r => Text -> Sem r () Source #
Log a message with the Error
severity.
crit :: HasCallStack => Member Log r => Text -> Sem r () Source #
Log a message with the Crit
severity.
formatLogEntry :: LogEntry LogMessage -> Text Source #
Default formatter for the default message type.
A log message's severity, or log level.
Instances
Enum Severity Source # | |
Defined in Polysemy.Log.Data.Severity | |
Eq Severity Source # | |
Show Severity Source # | |
Interpreters
interpretLogStderrWith :: Members [Embed IO, GhcTime] r => (LogEntry LogMessage -> Text) -> InterpreterFor Log r Source #
interpretLogStderrConc :: Members [Resource, Async, Race, Embed IO] r => InterpreterFor Log r Source #
Like interpretLogStderr
, but process messages concurrently.
interpretLogStderr :: Members [Embed IO, GhcTime] r => InterpreterFor Log r Source #
Interpret Log
by printing to stderr, using the default formatter.
Since this adds a timestamp, it has a dependency on GhcTime
.
Use interpretLogStderr'
for a variant that interprets GhcTime
in-place.
interpretLogStderr' :: Member (Embed IO) r => InterpreterFor Log r Source #
interpretLogStdoutWith :: Members [Embed IO, GhcTime] r => (LogEntry LogMessage -> Text) -> InterpreterFor Log r Source #
interpretLogStdoutConc :: Members [Resource, Async, Race, Embed IO] r => InterpreterFor Log r Source #
Like interpretLogStdout
, but process messages concurrently.
interpretLogStdout :: Members [Embed IO, GhcTime] r => InterpreterFor Log r Source #
Interpret Log
by printing to stderr, using the default formatter.
Since this adds a timestamp, it has a dependency on GhcTime
.
Use interpretLogStdout'
for a variant that interprets GhcTime
in-place.
interpretLogStdout' :: Member (Embed IO) r => InterpreterFor Log r Source #
interpretLogDataLog :: Members [DataLog (LogEntry LogMessage), GhcTime] r => InterpreterFor Log r Source #
interpretLogDataLog' :: Members [DataLog (LogEntry LogMessage), Embed IO] r => InterpretersFor [Log, LogMetadata LogMessage, GhcTime] r Source #
interpretLogOutput :: Member (Output LogMessage) r => InterpreterFor Log r Source #
interpretLogNull :: InterpreterFor Log r Source #
Interpret Log
by discarding all messages.
interpretLogAtomic :: Member (Embed IO) r => InterpretersFor [Log, AtomicState [LogMessage]] r Source #
Interpret Log
by prepending each message to a list in an AtomicState
, then interpret the AtomicState
in a
TVar
.
interpretLogAtomic' :: Member (AtomicState [LogMessage]) r => InterpreterFor Log r Source #
Interpret Log
by prepending each message to a list in an AtomicState
.
Concurrent Logging
:: forall msg r a. Members [DataLog msg, Resource, Async, Race, Embed IO] r | |
=> Int | Queue size. When the queue fills up, the interceptor will block. |
-> Sem r a | |
-> Sem r a |
Intercept DataLog
for concurrent processing.
Creates a queue and starts a worker thread.
All log messages received by the interceptor in interceptDataLogConcWithLocal
are written to the queue and sent to
the next DataLog
interpreter when the thread reads from the queue.
Since this is an interceptor, it will not remove the effect from the stack, but relay it to another interpreter:
interpretDataLogAtomic (interceptDataLogConc 64 (DataLog.dataLog "message"))