| Safe Haskell | Safe |
|---|---|
| Language | Haskell2010 |
Di
Description
Intended module usage:
import Di (Di) import qualified Di
- data Di path msg
- mkDi :: (MonadIO m, Monoid path) => (Level -> UTCTime -> path -> msg -> IO ()) -> m (Di path msg)
- push :: Di path msg -> path -> Di path msg
- path :: Di path' msg -> (path -> path') -> Di path msg
- msg :: Di path msg' -> (msg -> msg') -> Di path msg
- level :: Di path msg -> Level -> Di path msg
- data Level
- dbg :: MonadIO m => Di path msg -> msg -> m ()
- inf :: MonadIO m => Di path msg -> msg -> m ()
- wrn :: MonadIO m => Di path msg -> msg -> m ()
- err :: MonadIO m => Di path msg -> msg -> m ()
- dbg' :: MonadIO m => Di path msg -> msg -> m ()
- inf' :: MonadIO m => Di path msg -> msg -> m ()
- wrn' :: MonadIO m => Di path msg -> msg -> m ()
- err' :: MonadIO m => Di path msg -> msg -> m ()
- mkDiTextStderr :: MonadIO m => m (Di Text Text)
- mkDiTextFileHandle :: MonadIO m => Handle -> m (Di Text Text)
Documentation
allows you to to log messages of type Di path msgmsg, under a scope
identified by path (think of path as a filesystem path).
Each msg gets logged together with its Level, path and the
UTCTime timestamp stating when the logging requests was made.
Even though logging is usually associated with rendering text, Di makes no
assumption about the types of the msg values being logged, nor the path
values that convey their scope. Instead, it delays conversion from these
precise types into the ultimately desired raw representation as much as
possible. This makes it possible to log more precise information (for
example, logging a datatype of your own without having to convert it to text
first), richer scope paths (for example, the scope could be a
Map that gets enriched with more information as we push
down the path). This improves type safety, as well as the composability of
the path and msg values. In particular, path and msg are
contravariant values (see the path and msg functions).
Contrary to other logging approaches based on monadic interfaces, a Di is a
value that is expected to be passed around explicitly. A Di can be safely
used concurrently, and messages are rendered in the order they were submitted
for logging, both in the case of synchronous logging (e.g., err) and
asynchronous logging (e.g., err').
Di is pronounced as "dee" (not "die" nor "dye" nor "day"). "Di" is
the spanish word for an imperative form of the verb "decir", which in
english means "to say".
Arguments
| :: (MonadIO m, Monoid path) | |
| => (Level -> UTCTime -> path -> msg -> IO ()) | |
| -> m (Di path msg) |
Build a Di from a logging function.
push :: Di path msg -> path -> Di path msg Source #
Push a new path to the Di.
The passed in Di can continue to be used even after using push or the
returned Di.
See mkDiTextStderr for an example behaviour.
path :: Di path' msg -> (path -> path') -> Di path msg Source #
A Di is contravariant in its path argument.
This function is used to go from a more general to a more specific type
of path. For example, [ is a more specific type than Int][,
since the former clearly conveys the idea of a list of numbers, whereas the
latter could be a list of anything that is representable as String]String, such as
dictionary words. We can convert from the more general to the more specific
path type using this path function:
path(x ::Di[String] msg) (mapshow) ::Di[Int] msg
The Monoidal behavior of the original path' is preserved in the resulting
Di.
msg :: Di path msg' -> (msg -> msg') -> Di path msg Source #
A Di is contravariant in its msg argument.
This function is used to go from a more general to a more specific type
of msg. For example, is a more specific type than Int, since
the former clearly conveys the idea of a numbers, whereas the latter could be
a anything that is representable as StringString, such as a dictionary word. We
can convert from the more general to the more specific msg type using this
msg function:
msg(x ::DipathString)show::DipathInt
level :: Di path msg -> Level -> Di path msg Source #
Returns a new Di on which messages below the given Level are not
logged, where ther ordering of levels is as follow:
DBG<INF<WRN<ERR
For example, will prevent level x WRNDBG and INF from being logged.
Notice that will allow messages with a level greater than or
equal to level di xx even if they had been previously silenced in the given di.
Synchronous logging
Asynchronous logging
dbg' :: MonadIO m => Di path msg -> msg -> m () Source #
Asynchronously log a message with DBG level by queueing it in FIFO
order to be logged in a different thread as soon as possible. The timestamp
of the logged message will correctly represent the time of the dbg' call.
WARNING This function returns immediately, which makes it ideal for usage in tight loops. However, if logging the message fails later, you won't be able to catch the relevant exception.
inf' :: MonadIO m => Di path msg -> msg -> m () Source #
Asynchronously log a message with INF level by queueing it in FIFO
order to be logged in a different thread as soon as possible. The timestamp
of the logged message will correctly represent the time of the inf' call.
WARNING This function returns immediately, which makes it ideal for usage in tight loops. However, if logging the message fails later, you won't be able to catch the relevant exception.
wrn' :: MonadIO m => Di path msg -> msg -> m () Source #
Asynchronously log a message with WRN level by queueing it in FIFO
order to be logged in a different thread as soon as possible. The timestamp
of the logged message will correctly represent the time of the wrn' call.
WARNING This function returns immediately, which makes it ideal for usage in tight loops. However, if logging the message fails later, you won't be able to catch the relevant exception.
err' :: MonadIO m => Di path msg -> msg -> m () Source #
Asynchronously log a message with ERR level by queueing it in FIFO
order to be logged in a different thread as soon as possible. The timestamp
of the logged message will correctly represent the time of the err' call.
WARNING This function returns immediately, which makes it ideal for usage in tight loops. However, if logging the message fails later, you won't be able to catch the relevant exception.
Backends
mkDiTextStderr :: MonadIO m => m (Di Text Text) Source #
Text is written to stderr using the system's locale encoding.
> d0 <-mkDiTextStderr>dbgd0 "a" DBG 2017-05-06T19:01:27:306168750000Z: a > let d1 = push d0 "f/oo" -- '/' is converted to '.' >infd1 "b" INF 2017-05-06T19:01:27:314333636000Z f.oo: b > let d2 = push d1 "b ar" -- ' ' is converted to '_' >wrnd2 "c" WRN 2017-05-06T19:01:27:322092498000Z f.oo/b_ar: c > let d3 = push d2 "qux" >errd3 "d" ERR 2017-05-06T19:01:27:326704385000Z f.oo/b_ar/qux: d >errd0 "e\nf" -- d0, of course, still works ERR 2017-05-06T19:01:27:823167007000Z: e\nf