-- | Fast start

--

-- Create log config:

--

-- @

--myCfg = logCfg [(\"\", Info), (\"app\", Trace), (\"app.sub\", Debug)]

-- @

--

-- Create log and run log monad

--

-- @

--run ∷ IO ()

--run = runLog myCfg [handler text (file \"out.log\")] $ yourFunction

-- @

--

-- Function within log monad:

--

-- @

--yourFunction ∷ MonadLog m ⇒ m ()

--yourFunction = component \"app\" $ scope \"your\" $ do

--	sendLog Trace \"Hello from your function\"

-- @

--

-- Each component can have different level in config, subcomponents are specified with \'.\'

-- Components have independent scopes

-- Scopes can be nested and separated with \'/\':

--

-- @

--function2 ∷ MonadLog m ⇒ m ()

--function2 = component \"app.sub\" $ scope \"foo\" $ do

--	scope \"bar/baz\" $ do

--		sendLog Info \"Component app.sub and scope foo/bar/baz\"

--		sendLog Trace \"Invisible: app.sub configured with debug level\"

--	sendLog Info \"Same component and scope foo\"

--	component \"module\" $ sendLog Info \"Component module and root scope\"

-- @

--

-- You can update config with @updateLogConfig@ (or @modifyLogConfig@ within log monad) function

-- And change handlers with @updateLogHandlers@ (@modifyLogHandlers@)

-- 

-- There're also global logger @globalLog@, that can be used with @runGlobalLog@

--

-- @

--test ∷ IO ()

--test = do

--	updateLogHandlers globalLog ([handler text (file \"test.log\")]:)

--	runGlobalLog $ do

--		sendLog Info \"This will go to test.log too\"

--		modifyLogConfig (set (ix \"\") Debug)

--		sendLog Debug \"Now debug is logged too\"

-- @

--

module System.Log.Simple (

	module System.Log.Simple.Base,

	module System.Log.Simple.Monad,

	module System.Log.Simple.Text,

	module System.Log.Simple.Stream,

	module System.Log.Simple.File,



	globalLog,

	runGlobalLog, runConsoleLog, runLogMsgs, runLogTexts

	) where



import Prelude.Unicode



import Control.Monad.IO.Class

import Control.Monad.Catch (MonadMask)

import Control.Concurrent

import Data.Maybe

import Data.Text (Text)

import System.IO.Unsafe (unsafePerformIO)



import System.Log.Simple.Base (

	Level(..), Message, Converter, Consumer, LogHandler, handler,

	LogConfig(..), defCfg, logCfg, componentCfg, Log(..),

	newLog, rootLog, getLog, subLog,

	updateLogConfig, updateLogHandlers, writeLog, stopLog)

import System.Log.Simple.Monad (

	MonadLog(..), LogT(..), noLog, withLog, runLog, sendLog,

	component, scope_, scope, scopeM, scoper, scoperM, trace,

	modifyLogConfig, modifyLogHandlers)

import System.Log.Simple.Text

import System.Log.Simple.Stream

import System.Log.Simple.File

import System.Log.Simple.Chan



globalLog  Log

globalLog = unsafePerformIO $ newLog defCfg [handler text coloredConsole]



runGlobalLog  LogT m a  m a

runGlobalLog = withLog globalLog



runConsoleLog  (MonadIO m, MonadMask m)  LogConfig  LogT m a  m a

runConsoleLog cfg = runLog cfg [handler text coloredConsole]



runLogChan  (MonadIO m, MonadMask m)  (Chan w  LogHandler)  LogConfig  LogT m a  m (a, [w])

runLogChan c cfg act = do

	ch  liftIO newChan

	mch  liftIO newChan

	_  liftIO $ forkIO $ getChanContents ch >>= mapM_ (writeChan mch . Just)

	r  runLog cfg [c ch] act

	liftIO $ writeChan mch Nothing

	msgs  liftIO ((catMaybes  takeWhile isJust) <$> getChanContents mch)

	return (r, msgs)



runLogMsgs  (MonadIO m, MonadMask m)  LogConfig  LogT m a  m (a, [Message])

runLogMsgs = runLogChan chan



runLogTexts  (MonadIO m, MonadMask m)  Converter Text  LogConfig  LogT m a  m (a, [Text])

runLogTexts txt = runLogChan (handler txt  chan)