hslogger-1.0.4: Versatile logging frameworkSource codeContentsIndex
MaintainerJohn Goerzen <jgoerzen@complete.org>
Basic Types
Re-Exported from System.Log
Logging Messages
Utility Functions
Logging to a particular Logger by object
Logger Manipulation
Finding / Creating Loggers
Modifying Loggers
Saving Your Changes

Haskell Logging Framework, Primary Interface

Written by John Goerzen, jgoerzen@complete.org

Welcome to the error and information logging system for Haskell.

This system is patterned after Python's logging module, http://www.python.org/doc/current/lib/module-logging.html and some of the documentation here was based on documentation there.

To log a message, you perform operations on Loggers. Each Logger has a name, and they are arranged hierarchically. Periods serve as separators. Therefore, a Logger named "foo" is the parent of loggers "foo.printing", "foo.html", and "foo.io". These names can be anything you want. They're used to indicate the area of an application or library in which a logged message originates. Later you will see how you can use this concept to fine-tune logging behaviors based on specific application areas.

You can also tune logging behaviors based upon how important a message is. Each message you log will have an importance associated with it. The different importance levels are given by the Priority type. I've also provided some convenient functions that correspond to these importance levels: debugM through emergencyM log messages with the specified importance.

Now, an importance level (or Priority) is associated not just with a particular message but also with a Logger. If the Priority of a given log message is lower than the Priority configured in the Logger, that message is ignored. This way, you can globally control how verbose your logging output is.

Now, let's follow what happens under the hood when you log a message. We'll assume for the moment that you are logging something with a high enough Priority that it passes the test in your Logger. In your code, you'll call logM or something like debugM to log the message. Your Logger decides to accept the message. What next?

Well, we also have a notion of handlers (LogHandlers, to be precise). A LogHandler is a thing that takes a message and sends it somewhere. That "somewhere" may be your screen (via standard error), your system's logging infrastructure (via syslog), a file, or other things. Each Logger can have zero or more LogHandlers associated with it. When your Logger has a message to log, it passes it to every LogHandler it knows of to process. What's more, it is also passed to /all handlers of all ancestors of the Logger/, regardless of whether those Loggers would normally have passed on the message.

To give you one extra little knob to turn, LogHandlers can also have importance levels (Priority) associated with them in the same way that Loggers do. They act just like the Priority value in the Loggers -- as a filter. It's useful, for instance, to make sure that under no circumstances will a mere DEBUG message show up in your syslog.

There are three built-in handlers given in two built-in modules: System.Log.Handler.Simple and System.Log.Handler.Syslog.

There is a special logger known as the root logger that sits at the top of the logger hierarchy. It is always present, and handlers attached there will be called for every message. You can use getRootLogger to get it or rootLoggerName to work with it by name.

Here's an example to illustrate some of these concepts:

 import System.Log.Logger
 import System.Log.Handler.Syslog
 -- By default, all messages of level WARNING and above are sent to stderr.
 -- Everything else is ignored.
 -- "MyApp.Component" is an arbitrary string; you can tune
 -- logging behavior based on it later.
 main = do
        debugM "MyApp.Component"  "This is a debug message -- never to be seen"
        warningM "MyApp.Component2" "Something Bad is about to happen."
        -- Copy everything to syslog from here on out.
        s <- openlog "SyslogStuff" [PID] USER DEBUG
        updateGlobalLogger rootLoggerName (addHandler s)
        errorM "MyApp.Component" "This is going to stderr and syslog."

        -- Now we'd like to see everything from BuggyComponent
        -- at DEBUG or higher go to syslog and stderr.
        -- Also, we'd like to still ignore things less than
        -- WARNING in other areas.
        -- So, we adjust the Logger for MyApp.Component.

        updateGlobalLogger "MyApp.BuggyComponent"
                           (setLevel DEBUG)

        -- This message will go to syslog and stderr
        debugM "MyApp.BuggyComponent" "This buggy component is buggy"
        -- This message will go to syslog and stderr too.
        warningM "MyApp.BuggyComponent" "Still Buggy"
        -- This message goes nowhere.
        debugM "MyApp.WorkingComponent" "Hello"
data Logger
data Priority
logM :: String -> Priority -> String -> IO ()
debugM :: String -> String -> IO ()
infoM :: String -> String -> IO ()
noticeM :: String -> String -> IO ()
warningM :: String -> String -> IO ()
errorM :: String -> String -> IO ()
criticalM :: String -> String -> IO ()
alertM :: String -> String -> IO ()
emergencyM :: String -> String -> IO ()
traplogging :: String -> Priority -> String -> IO a -> IO a
logL :: Logger -> Priority -> String -> IO ()
getLogger :: String -> IO Logger
getRootLogger :: IO Logger
addHandler :: LogHandler a => a -> Logger -> Logger
setHandlers :: LogHandler a => [a] -> Logger -> Logger
getLevel :: Logger -> Priority
setLevel :: Priority -> Logger -> Logger
saveGlobalLogger :: Logger -> IO ()
updateGlobalLogger :: String -> (Logger -> Logger) -> IO ()
Basic Types
data Logger Source
Re-Exported from System.Log
data Priority Source

Priorities are used to define how important a log messgae is. Users can filter log messages based on priorities.

These have their roots on the traditional syslog system. The standard definitions are given below, but you are free to interpret them however you like. They are listed here in ascending importance order.

DEBUGDebug messages
NOTICENormal runtime conditions
WARNINGGeneral Warnings
ERRORGeneral Errors
CRITICALSevere situations
ALERTTake immediate action
EMERGENCYSystem is unusable
show/hide Instances
Logging Messages
:: StringName of the logger to use
-> PriorityPriority of this message
-> StringThe log text itself
-> IO ()
Log a message using the given logger at a given priority.
Utility Functions
:: StringLogger name
-> StringLog message
-> IO ()
Log a message at DEBUG priority
:: StringLogger name
-> StringLog message
-> IO ()
Log a message at INFO priority
:: StringLogger name
-> StringLog message
-> IO ()
Log a message at NOTICE priority
:: StringLogger name
-> StringLog message
-> IO ()
Log a message at WARNING priority
:: StringLogger name
-> StringLog message
-> IO ()
Log a message at ERROR priority
:: StringLogger name
-> StringLog message
-> IO ()
Log a message at CRITICAL priority
:: StringLogger name
-> StringLog message
-> IO ()
Log a message at ALERT priority
:: StringLogger name
-> StringLog message
-> IO ()
Log a message at EMERGENCY priority
traplogging :: String -> Priority -> String -> IO a -> IO aSource

Traps exceptions that may occur, logging them, then passing them on.

Takes a logger name, priority, leading description text (you can set it to "" if you don't want any), and action to run.

Logging to a particular Logger by object
logL :: Logger -> Priority -> String -> IO ()Source
Log a message, assuming the current logger's level permits it.
Logger Manipulation

These functions help you work with loggers. There are some special things to be aware of.

First of all, whenever you first access a given logger by name, it magically springs to life. It has a default Priority of DEBUG and an empty handler list -- which means that it will inherit whatever its parents do.

Finding / Creating Loggers
getLogger :: String -> IO LoggerSource
Returns the logger for the given name. If no logger with that name exists, creates new loggers and any necessary parent loggers, with no connected handlers.
getRootLogger :: IO LoggerSource
Returns the root logger.
Modifying Loggers

Keep in mind that "modification" here is modification in the Haskell sense. We do not actually cause mutation in a specific Logger. Rather, we return you a new Logger object with the change applied.

Also, please note that these functions will not have an effect on the global Logger hierarchy. You may use your new Loggers locally, but other functions won't see the changes. To make a change global, you'll need to use updateGlobalLogger or saveGlobalLogger.

addHandler :: LogHandler a => a -> Logger -> LoggerSource
Add handler to Logger. Returns a new Logger.
setHandlers :: LogHandler a => [a] -> Logger -> LoggerSource
Set the 'Logger'\'s list of handlers to the list supplied. All existing handlers are removed first.
getLevel :: Logger -> PrioritySource
Returns the level of the logger. Items beneath this level will be ignored.
setLevel :: Priority -> Logger -> LoggerSource
Sets the level of the Logger. Returns a new Logger object with the new level.
Saving Your Changes
These functions commit changes you've made to loggers to the global logger hierarchy.
saveGlobalLogger :: Logger -> IO ()Source
Updates the global record for the given logger to take into account any changes you may have made.
:: StringLogger name
-> Logger -> LoggerFunction to call
-> IO ()

Helps you make changes on the given logger. Takes a function that makes changes and writes those changes back to the global database. Here's an example from above ("s" is a LogHandler):

 updateGlobalLogger "MyApp.BuggyComponent"
                    (setLevel DEBUG . setHandlers [s])
Produced by Haddock version 2.3.0