Safe Haskell | None |
---|---|
Language | Haskell2010 |
The Logger
type of logging back-ends.
Synopsis
- data LoggerEnv = LoggerEnv {}
- data Logger
- mkLogger :: Text -> (LogMessage -> IO ()) -> IO Logger
- mkBulkLogger :: Text -> ([LogMessage] -> IO ()) -> IO () -> IO Logger
- mkBulkLogger' :: Int -> Int -> Text -> ([LogMessage] -> IO ()) -> IO () -> IO Logger
- execLogger :: Logger -> LogMessage -> IO ()
- waitForLogger :: Logger -> IO ()
- shutdownLogger :: Logger -> IO ()
Documentation
The state that every LogT
carries around.
An object used for communication with a logger thread that
outputs LogMessage
s using e.g. PostgreSQL, Elasticsearch or
stdout (depending on the back-end chosen).
mkLogger :: Text -> (LogMessage -> IO ()) -> IO Logger Source #
Start a logger thread that consumes one queued message at a time.
mkBulkLogger :: Text -> ([LogMessage] -> IO ()) -> IO () -> IO Logger Source #
Start an asynchronous logger thread that consumes all queued
messages once per second. Uses a bounded queue internally to avoid
space leaks. To make sure that the messages get written out in the
presence of exceptions, use high-level wrappers like withLogger
,
withElasticSearchLogger
or
withBulkStdOutLogger
instead of
this function directly.
Note: some messages can be lost when the main thread shuts down without making sure that all logger threads have written out all messages, because in that case child threads are not given a chance to clean up by the RTS. This is apparently a feature: https://mail.haskell.org/pipermail/haskell-cafe/2014-February/112754.html
To work around this issue, make sure that the main thread doesn't
exit until all its children have terminated. The async
package
makes this easy.
Problematic example:
import Control.Concurrent.Async main :: IO () main = do logger <-elasticSearchLogger
a <-async
(withElasticSearchLogger
$ \logger ->runLogT
"main" logger $logTrace_
"foo") -- Main thread exits without waiting for the child -- to finish and without giving the child a chance -- to do proper cleanup.
Fixed example:
import Control.Concurrent.Async main :: IO () main = do logger <-elasticSearchLogger
a <-async
(withElasticSearchLogger
$ \logger ->runLogT
"main" logger $logTrace_
"foo")wait
a -- Main thread waits for the child to finish, giving -- it a chance to shut down properly. This works even -- in the presence of exceptions in the child thread.
:: Int | queue capacity (default 1000000) |
-> Int | thread delay (microseconds, default 1000000) |
-> Text | logger name |
-> ([LogMessage] -> IO ()) | write |
-> IO () | flush |
-> IO Logger |
Like mkBulkLogger
, but with configurable queue size and thread delay.
Since: 0.7.4.0
execLogger :: Logger -> LogMessage -> IO () Source #
Execute logger to serialize a LogMessage
.
waitForLogger :: Logger -> IO () Source #
Wait until all LogMessage
s stored in the internal queue are
serialized.