-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Simple, configurable logging -- -- SimpleLog allows configurable multi-threaded logging @package SimpleLog @version 0.1.0.2 -- | This module defines the Format datatype that describes how to -- format a log line. It also defines a template function $(format _) -- :: Format that allows C-style string formatting. The -- format string is thus parsed at compile time. -- -- The format string may contain the following elements: -- --
-- logFormat = $(format "%d(%T) (%s) %t: %m") ---- -- Which when logging with logI "Something" will produce -- something like: -- --
-- 14:49:06 (INFO ) main: Something ---- -- Example for escaping ')' in the datetime format string: -- --
-- logFormat = $(format "%d((%F\\)(%T\\)) %m") ---- -- Which when logging with logI "Something" will produce: -- --
-- (2013-10-02)(16:26:21) Something ---- -- Note how we need an additional '\' because of Haskell strings module System.Log.SLog.Format -- | A FormatElem is a formatting element data FormatElem MessageElem :: FormatElem SeverityElem :: FormatElem StringElem :: Text -> FormatElem DateTimeElem :: (ZonedTime -> Text) -> FormatElem ThreadElem :: FormatElem -- | Format is the type of a full format. It is simply a list of -- FormatElems type Format = [FormatElem] -- | $(format _) :: Format is a template function -- that parses the passed in format string, then finalises it and returns -- a Format. format :: String -> ExpQ instance Show FormatElemTH instance Lift Text -- | SimpleLog is a library for convenient and configurable logging. It -- uses the usual monad transformer + associated class design: -- SLogT and MonadSLog. -- -- Example usage: -- --
-- import System.Log.SLog -- -- main = simpleLog "Example.log" $ do -- logD "Some debugging information" -- logI "This is some other information" -- logW "Something bad is about to happen" -- logE "Something bad happened" ---- -- The above sample code when run will produce output similar to this: -- --
-- 2013-10-02 14:17:40 | INFO | [ThreadId 58] This is some other information -- 2013-10-02 14:17:40 | WARNING | [ThreadId 58] Something bad is about to happen -- 2013-10-02 14:17:40 | ERROR | [ThreadId 58] Something bad happened ---- -- Note how the debug line is not displayed. This is because the default -- configuration (defaultLogConfig) only logs to stdout when the -- severity is >= INFO. The above code will also append the log -- lines to the file "Example.log", including the debug line. -- -- The following example shows how one can fine tune SimpleLog as well as -- how to fork other logging threads. -- --
-- -- Our log configuration specifies that no ANSI colouring should be used, all log lines
-- -- should be written to the TChan, and >= INFO severity lines should be written to the
-- -- stdout synchronously.
-- logConfig :: TChan LogLine -> LogConfig
-- logConfig tchan
-- = LogConfig { ansiColours = False
-- , loggers = [ (anySev, TChanLogger tchan)
-- , ((>= INFO), StdoutLogger Sync)
-- ] }
--
-- -- Our custom logging format
-- logFormat :: Format
-- logFormat = $(format "%d(%T) (%s) %t: %m")
--
-- -- The main thread will fork a child thread, then wait until everything is flushed, then
-- -- count how many messages have been written in total to the TChan (which will be all
-- -- messages as our filter passes through everything)
-- main :: IO ()
-- main = do
-- tchan <- newTChanIO
-- (_, fkey) <- runSLogT (logConfig tchan) logFormat "main" $ do
-- logS "Main thread started successfully"
-- logD "This will not appear on stdout"
-- _ <- forkSLog "child" $ do
-- logS "I am the child"
-- liftIO $ threadDelay 5000000
-- logW "CHILD SHUTTING DOWN"
-- logI "Exiting main thread"
-- waitFlush fkey
-- c <- countTChan tchan
-- putStrLn $ show c ++ " messages have been logged in total"
--
-- -- Counts the number of elements in the TChan (and pops them all)
-- countTChan :: TChan a -> IO Int
-- countTChan tchan = do
-- let count = do
-- em <- isEmptyTChan tchan
-- if em then return 0
-- else readTChan tchan >> (1 +) <$> count
-- atomically count
--
--
-- The above code when run will produce something like this:
--
-- -- 17:35:15 (SUCCESS) main: Main thread started successfully -- 17:35:15 (SUCCESS) child: I am the child, waiting for 5 seconds... -- 17:35:15 (INFO ) main: Exiting main thread -- 17:35:20 (WARNING) child: CHILD SHUTTING DOWN -- 5 messages have been logged in total --module System.Log.SLog -- | The SLogT monad transformer is simply a ResourceT with an -- environment data SLogT m a -- | This is a simple monad for the bottom of one's monad stack. type SLog = SLogT IO -- | runSLogT runs an SLogT given a LogConfig, -- Format and the current thread's name. It returns a -- FlushKey besides the usual return value. runSLogT :: (MonadResource m, MonadBaseControl IO m) => LogConfig -> Format -> String -> SLogT m a -> m (a, FlushKey) -- | simpleLog uses the default configuration with the specified log -- file name. It also waits using waitFlush until all resources -- have been released. simpleLog :: (MonadResource m, MonadBaseControl IO m) => FilePath -> SLogT m a -> m a -- | A FlushKey is returned when an SLogT is run. You may -- wait on it with waitFlush. data FlushKey -- | waitFlush will only return when all resources have been -- released and all streams have been flushed. Note that this includes -- resources allocated by the user using the exposed MonadResource -- instance. -- -- All threads internally accounted for are signaled to exit (they will -- first finish processing of all remaining jobs) when the SLogT -- is run, however it is the user's responsibility to shut down threads -- forked with forkSLog or fork before waitFlush can -- return. waitFlush :: FlushKey -> IO () -- | The class of monads that can perform logging class MonadIO m => MonadSLog m where log sev = lift . log sev log :: MonadSLog m => Severity -> Text -> m () -- | Log a DEBUG message logD :: MonadSLog m => String -> m () -- | Log an INFO message logI :: MonadSLog m => String -> m () -- | Log a SUCCESS message logS :: MonadSLog m => String -> m () -- | Log a WARNING message logW :: MonadSLog m => String -> m () -- | Log an ERROR message logE :: MonadSLog m => String -> m () -- | The Logger type specifies the types of sinks we can log to. data Logger -- | FileLogger specifies a file to be logged in. Note that symbolic -- links will be resolved using canonicalizePath when deciding -- whether two FileLoggers point to the same file. FileLogger :: Sync -> FilePath -> Logger -- | StdoutLogger logs to the stdout StdoutLogger :: Sync -> Logger -- | StderrLogger logs to the stderr StderrLogger :: Sync -> Logger -- | TChanLogger logs to a specified TChan. Note that -- LogLines are written instead of the final formatted text. If -- you wish to use the final text use formatLine. TChanLogger :: (TChan LogLine) -> Logger -- | Sync is a type to specify whether a logger should log -- synchronously or asynchronously. Syncronous logging means that the -- logging thread will block until the message has been written and -- flushed to the sink. Asynchronous logging means that the logging -- thread will write to a work queue and move on. The work queue will be -- read by a dedicated thread that is forked for each sink. data Sync Sync :: Sync Async :: Sync -- | LogLine is a log message together with the severity, time of -- logging and the logging thread's name. data LogLine LogLine :: Severity -> Text -> ZonedTime -> Text -> LogLine logSeverity :: LogLine -> Severity logMessage :: LogLine -> Text logTimestamp :: LogLine -> ZonedTime logThread :: LogLine -> Text -- | The type of severities with increasing importance data Severity DEBUG :: Severity INFO :: Severity SUCCESS :: Severity WARNING :: Severity ERROR :: Severity -- | Filter is the type of logging filters. Filters may only -- depend on the Severity. type Filter = Severity -> Bool -- | anySev allows all lines to be logged. anySev :: Filter -- | LogConfig is the configuration of SLogT data LogConfig LogConfig :: Bool -> [(Filter, Logger)] -> LogConfig -- | Specifies whether ANSI colouring should be used when logging to -- stdout/stderr ansiColours :: LogConfig -> Bool -- | The list of loggers together with the associated filters loggers :: LogConfig -> [(Filter, Logger)] -- | defaultLogConfig is the default log configuration. It writes -- all non-DEBUG messages to the stdout synchronously and all messages to -- a specified file asynchronously. defaultLogConfig :: FilePath -> LogConfig -- | The default log format, which currently is $(format "%d(%F %T) | -- %s | [%t] %m"). See System.Log.SLog.Format for more -- details on format strings. defaultLogFormat :: Format -- | forkSLog forks an SLogT thread with the specified thread -- name. forkSLog :: (MonadBaseControl IO m, MonadIO m) => String -> SLogT m () -> SLogT m ThreadId -- | formatLine formats the given LogLine using the specified -- Format. The Boolean determines whether formatLine -- should insert ANSI colour codes or not. formatLine :: Bool -> Format -> LogLine -> Text -- | unsafeUnliftSLog gives you an unsafe unlift of an SLogT by -- assuming that any unlifted computation will finish earlier than the -- runSLogT of the calling thread. It is unsafe because if the unlifted -- computation doesn't finish earlier then it may access deallocated -- resources. This is useful when a library is implicitly forking but we -- still need to log in the forked threads, and we know that the child -- threads will finish earlier than the parent. An example is -- Network.WebSockets unsafeUnliftSLogT :: (Monad m, MonadBaseControl IO m) => ((forall a. SLogT m a -> m a) -> SLogT m b) -> SLogT m b instance (MonadBase IO m, MonadThrow m, MonadIO m) => MonadResource (SLogT m) instance MonadBase IO m => MonadBase IO (SLogT m) instance Show Severity instance Read Severity instance Eq Severity instance Ord Severity instance Eq Sync instance Eq Logger instance Functor m => Functor (SLogT m) instance Monad m => Monad (SLogT m) instance MonadIO m => MonadIO (SLogT m) instance Applicative m => Applicative (SLogT m) instance MonadThrow m => MonadThrow (SLogT m) instance MonadIO m => MonadSLog (SLogT m) instance (MonadBaseControl IO m, MonadIO m) => Forkable (SLogT m) (SLogT m) instance Semigroup InitLogger instance MonadTrans SLogT instance MonadBaseControl IO m => MonadBaseControl IO (SLogT m) instance MonadTransControl SLogT instance MonadSLog m => MonadSLog (ResourceT m) instance MonadSLog m => MonadSLog (ContT r m) instance (MonadSLog m, Error e) => MonadSLog (ErrorT e m) instance MonadSLog m => MonadSLog (ReaderT s m) instance MonadSLog m => MonadSLog (StateT s m)