-- 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: -- -- -- -- The datetime FORMAT is a UNIX style format string detailed in -- Data.Time.Format. The only difference is that closing brackets -- ')' inside the datetime format must be escaped with a backslash. -- -- Example: -- --
--   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)