-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Simple log for Haskell -- -- Log library for Haskell with removing unnecessary traces @package simple-log @version 0.3.2 module System.Log.Simple.Base -- | Level of message data Level Trace :: Level Debug :: Level Info :: Level Warning :: Level Error :: Level Fatal :: Level -- | Scope politics data Politics Politics :: Level -> Level -> Politics [politicsLow] :: Politics -> Level [politicsHigh] :: Politics -> Level -- | Rule for politics data Rule Rule :: ([Text] -> Bool) -> (Politics -> Politics) -> Rule [rulePath] :: Rule -> [Text] -> Bool [rulePolitics] :: Rule -> Politics -> Politics type Rules = [Rule] -- | Default politics defaultPolitics :: Politics -- | Debug politics debugPolitics :: Politics -- | Trace politics tracePolitics :: Politics -- | Silent politics silentPolitics :: Politics -- | Supress all messages politics supressPolitics :: Politics -- | Make rule rule :: ([Text] -> Bool) -> (Politics -> Politics) -> Rule -- | Absolute scope-path absolute :: [Text] -> [Text] -> Bool -- | Relative scope-path relative :: [Text] -> [Text] -> Bool -- | Scope-path for child child :: ([Text] -> Bool) -> [Text] -> Bool -- | Root scope-path root :: [Text] -> Bool -- | Scope-path by text -- --
-- / -- root -- foo/bar -- relative -- /foo/bar -- absolute -- foo/bar/ -- child of relative -- /foo/bar/ -- child of absolute --path :: Text -> ([Text] -> Bool) -- | Rule by path (%=) :: Text -> (Politics -> Politics) -> Rule -- | Just set new politics politics :: Level -> Level -> Politics -> Politics -- | Use predefined politics use :: Politics -> Politics -> Politics -- | Set new low level low :: Level -> Politics -> Politics -- | Set new high level high :: Level -> Politics -> Politics -- | Log message data Message Message :: ZonedTime -> Level -> [Text] -> Text -> Message [messageTime] :: Message -> ZonedTime [messageLevel] :: Message -> Level [messagePath] :: Message -> [Text] [messageText] :: Message -> Text -- | Converts message some representation type Converter a = Message -> a data Consumer a Consumer :: (((a -> IO ()) -> IO ()) -> IO ()) -> Consumer a [withConsumer] :: Consumer a -> ((a -> IO ()) -> IO ()) -> IO () -- | Log entry, scope or message data Entry Entry :: Message -> Entry Scope :: Text -> Rules -> (IO ()) -> [Entry] -> Entry -- | Command to logger data Command EnterScope :: Text -> Rules -> Command LeaveScope :: (IO ()) -> Command PostMessage :: Message -> Command -- | Apply commands to construct list of entries entries :: [Command] -> [Entry] -- | Flatten entries to raw list of commands flatten :: [Entry] -> [Command] -- | Apply rules rules :: Rules -> [Text] -> [Entry] -> [Entry] -- | Logger type Logger = Consumer Message -- | Convert consumer creater to logger creater logger :: Converter a -> Consumer a -> Consumer Message -- | Type to initialize rule updater type RulesLoad = IO (IO Rules) -- | Log data Log Log :: (Command -> IO ()) -> IO Rules -> Log [logPost] :: Log -> Command -> IO () [logRules] :: Log -> IO Rules -- | Empty log noLog :: Log -- | Create log -- -- Messages from distinct threads are splitted in several chans, where -- they are processed, and then messages combined back and sent to -- log-thread newLog :: RulesLoad -> [Logger] -> IO Log -- | Write message to log writeLog :: MonadIO m => Log -> Level -> Text -> m () -- | New log-scope scopeLog_ :: MonadCatchIO m => Log -> Text -> m a -> m a -- | New log-scope with lifting exceptions as errors scopeLog :: MonadCatchIO m => Log -> Text -> m a -> m a -- | New log-scope with tracing scope result scoperLog :: MonadCatchIO m => Show a => Log -> Text -> m a -> m a instance GHC.Show.Show System.Log.Simple.Base.Message instance GHC.Read.Read System.Log.Simple.Base.Message instance GHC.Show.Show System.Log.Simple.Base.Politics instance GHC.Read.Read System.Log.Simple.Base.Politics instance GHC.Classes.Ord System.Log.Simple.Base.Politics instance GHC.Classes.Eq System.Log.Simple.Base.Politics instance GHC.Enum.Bounded System.Log.Simple.Base.Level instance GHC.Enum.Enum System.Log.Simple.Base.Level instance GHC.Show.Show System.Log.Simple.Base.Level instance GHC.Read.Read System.Log.Simple.Base.Level instance GHC.Classes.Ord System.Log.Simple.Base.Level instance GHC.Classes.Eq System.Log.Simple.Base.Level instance Control.DeepSeq.NFData System.Log.Simple.Base.Message module System.Log.Simple.Config -- | Parse rule -- -- Format: -- --
-- path: rule1, rule2 -- ---- -- where "path" is argument for path, and "rule" is one of -- --
-- /: use trace -- /foo: low trace -- foo/bar/quux: use silent --parseRule :: Text -> Writer [Text] Rule parseRules :: Text -> Writer [Text] Rules -- | Try parse rule ignoring errors parseRule_ :: Text -> Rule -- | Try parse rules ignoring errors parseRules_ :: Text -> Rules -- | Constant rules constant :: Rules -> IO (IO Rules) -- | Rules from mvar mvar :: MVar Rules -> IO (IO Rules) -- | Rules from file fileCfg :: FilePath -> Int -> IO (IO Rules) module System.Log.Simple.Monad withNoLog :: ReaderT Log m a -> m a withLog :: Log -> ReaderT Log m a -> m a log :: (MonadLog m) => Level -> Text -> m () scope_ :: (MonadLog m) => Text -> m a -> m a -- | Scope with log all exceptions scope :: (MonadLog m) => Text -> m a -> m a -- | Workaround: we must explicitely post LeaveScope scopeM_ :: (MonadLog m, MonadError e m) => Text -> m a -> m a -- | Scope with log exceptions from MonadError | Workaround: we must -- explicitely post LeaveScope scopeM :: (Show e, MonadLog m, MonadError e m) => Text -> m a -> m a -- | Scope with tracing result scoper :: (Show a, MonadLog m) => Text -> m a -> m a scoperM :: (Show e, Show a, MonadLog m, MonadError e m) => Text -> m a -> m a -- | Ignore error ignoreError :: (MonadLog m) => m () -> m () -- | Ignore MonadError error ignoreErrorM :: (MonadLog m, MonadError e m) => m () -> m () -- | Trace value trace :: (Show a, MonadLog m) => Text -> m a -> m a class (MonadCatchIO m) => MonadLog m askLog :: MonadLog m => m Log instance Control.Monad.CatchIO.MonadCatchIO m => System.Log.Simple.Monad.MonadLog (Control.Monad.Trans.Reader.ReaderT System.Log.Simple.Base.Log m) module System.Log.Simple.Text -- | Default time format defaultTimeFormat :: String -- | Text log converter with time format textFmt :: String -> Converter Text -- | Text log converter with default time format text :: Converter Text module System.Log.Simple.Console console :: Consumer Text module System.Log.Simple.File file :: FilePath -> Consumer Text -- | Fast start -- -- The best way is to define config file, which is auto reloaded -- periodically, so you can change config while program is running to -- turn on tracing some function. -- -- Typical config file with rule for root scope (see below for -- explanation): -- --
-- /: use default ---- -- If you want to trace scope named "foo", just add: -- --
-- /: use default -- foo: low trace ---- -- Now "foo" and children will be traced even there are no errors. To -- trace only "foo" without children: -- --
-- /: use default -- foo: low trace -- foo/: use default ---- -- "foo/" defines rules for children of "foo". -- -- Note, that by default all function will log their traces on error, so -- there is no need to turn on trace manually. You may want to turn on -- tracing when there are logic errors present without explicit errors -- (exceptions, or messages with error level). -- -- Now we can run our log with auto reloading config every 60 seconds: -- --
-- run :: IO () -- run = do -- l <- newLog (fileCfg "log.cfg" 60) [logger text (file "out.log")] -- withLog l yourFunction -- ---- -- And use it: -- --
-- yourFunction :: (MonadLog m) => m () -- yourFunction = scope "your" $ do -- log Trace "Hello from your function" -- ---- -- The main ideas of this log library are: -- --
-- test :: ReaderT Log IO () -- test = scope "test" $ do -- log Trace "Trace message" -- log Info "Starting test" -- s <- liftIO T.getLine -- when (T.null s) $ log Error "Oh no!" -- log Trace $ T.concat ["Your input: ", s] -- ---- -- When you input some valid string, it will produce output: -- --
-- 08/10/12 22:23:34 INFO test> Starting test -- abc -- ---- -- wihtout any traces -- -- But if you input empty strings, you'll get: -- --
-- 08/10/12 22:24:20 INFO test> Starting test -- 08/10/12 22:24:20 TRACE test> Trace message -- 08/10/12 22:24:21 ERROR test> Oh no! -- 08/10/12 22:24:21 TRACE test> Your input: -- ---- -- Note, that first Trace is written after Info, that's -- because logger don't know whether Trace message will be written -- or not, but he must write Info message immediately. But that's -- not a big problem. -- -- There are three scope functions: scope_, scope and -- scoper. scope_ is basic function. scope catches -- all exceptions and logs error with it, then rethrows. scoper is -- like scope, but logs (with Trace level) result of -- do-block. -- -- Of course, scopes can be nested: -- --
-- test :: ReaderT Log IO () -- test = scope "test" $ do -- log Trace "test trace" -- foo -- log Info "some info" -- bar -- -- foo :: ReaderT Log IO () -- foo = scope "foo" $ do -- log Trace "foo trace" -- -- bar :: ReaderT Log IO () -- bar = scope "bar" $ do -- log Trace "bar trace" -- log Error "bar error" -- ---- -- Output: -- --
-- 08/10/12 22:32:53 INFO test> some info -- 08/10/12 22:32:53 TRACE test/bar> bar trace -- 08/10/12 22:32:53 ERROR test/bar> bar error -- ---- -- Note, no messages for "foo" and no trace messages for "test", because -- error was in "bar", not in "foo". -- -- Code to run log: -- --
-- rules :: Rules -- rules = [] -- -- run :: IO () -- run = do -- l <- newLog (constant rules) [logger text console] -- withLog l test -- ---- -- Politics sets low and high levels. By default, -- low and high are INFO and WARN. Levels below low -- are "traces" (Trace and Debug by default). Levels above -- high are "errors" (Error and Fatal by default). -- -- If you set low to Trace, all messages will be written. -- If you set low to Debug and high to Fatal, -- "traces" (in this case only Trace) will be never written. -- -- Sometimes we need to trace function, but we don't want to write all -- traces. We can get this by setting rules. Rules changes politics for -- specified scope-path (scope-path is list of nested scopes, for example -- ["test"], ["test", "bar"], ["test", "bar", "baz", "quux"] etc.) -- -- For example, we want to trace function foo: -- --
-- rules = [ -- rule root $ use defaultPolitics, -- rule (relative ["foo"]) $ low Trace] -- ---- -- From now all scope-paths, that contains "foo" (all scopes with name -- "foo") will have politics with low set to Trace. -- -- We may adjust politics for scope foo, that is nested directly -- in scope quux: -- --
-- rules = [ -- rule root $ use defaultPolitics, -- relative ["quux", "foo"] $ low Trace] -- ---- -- And, of course, we may specify absolute path: -- --
-- rules = [ -- rule root $ use defaultPolitics, -- absolute ["bar", "baz", "foo"] $ low Trace] -- ---- -- Politics will be changed only for scope "foo", which is nested -- directly in "baz", which is nested in "bar", which is top scope. -- -- Another way to define rule is using special functions from -- System.Log.Config module: -- --
-- rules = [ -- "/" %= use defaultPolitics, -- "/bar/baz/foo" %= low Trace, -- "quux/foo" %= low Debug] -- ---- -- One more way to use special syntax for rules: -- --
-- rules = parseRules_ $ T.unlines [ -- "/: use default", -- "/bar/baz/foo: low trace", -- "quux/foo: low debug"] -- ---- -- Here "/" is for root, "/path" for absolute path, "path" for relative -- and "path/" for child of "path" (which may be also prefixed with "/" -- to be absolute) -- -- This syntax is useful to config log by file. Having file "log.cfg": -- --
-- /: use default -- /bar/baz/foo: low trace -- quux/foo: low debug ---- -- We can use it to config log -- --
-- l <- newLog (fileCfg "log.cfg" 60) [logger text console] ---- -- where 60 is period (in seconds) of auto reload or 0 for no reloading. module System.Log.Simple