hlogger-0.0.3.0: System/Log/HLogger.hs
-- | Module: $Header$
-- Description: Easy-to-use, concurrent and extendable logging framework
-- Copyright: Copyright © 2010-2011 Jon Kristensen
-- License: BSD-3
--
-- Maintainer: info@pontarius.org
-- Stability: unstable
-- Portability: portable
-- | This is a work in progress for a simple logging framework that aims to be
-- easy-to-use, concurrent and extendable through plug-ins. You cannot use
-- this module for logging directly, instead you want to use an HLogger
-- implementation. If you simply want to log messages to a file, consider
-- using the @SimpleLogger@ implementation. If you want a more complicated
-- logger, see below.
--
-- * Implementing a Customized Logger
--
-- If the loggers provided by the HLogger project (currently only
-- SimpleLogger) are insufficient for your application, implementing a custom
-- logging implementation on top of HLogger is simple. You can modify the
-- logger behaviour (how it logs), but not the logger's API (logging levels
-- and exported functions). Another limitation of HLogger implementations is
-- that they are immutable (operating in a static environment, cannot have
-- their state changed).
--
-- See the SimpleLogger module for an example on how an implementation can be
-- made.
module System.Log.HLogger ( ModuleName
, FunctionName
, Logger (..)
, LogMessage (..)
, LogLevel (..)
, logger ) where
import Control.Concurrent (forkIO)
import Control.Concurrent.Chan (Chan, newChan, writeChan)
import Prelude hiding (log)
-- | The name of the module issuing the logging instruction.
type ModuleName = String
-- | The name of the function issuing the logging instruction.
type FunctionName = String
-- | This object provides the logging API. Consult the documentation for the
-- logging implementation (or SimpleLogger) about how to acquire a Logger
-- object.
data Logger = Logger { -- | Logs a message.
loggerLog :: Maybe (ModuleName, FunctionName) ->
LogLevel -> String -> IO ()
-- | Stops the logger. This action is asynchronous.
, loggerStop :: IO () }
-- LogLevel indicates the importance of a log entry. The log levels are the
-- same as in the Syslog application. The below list is ordered by priority,
-- Debug being the least significant message.
data LogLevel = Debug | -- ^ Debug messages are the least significant kind
-- of messages
Info | -- ^ Purely informational message; consider Notice
-- instead if the message is significant
Notice | -- ^ Significant messages for normal conditions
Warning | -- ^ Warning condition message
Error | -- ^ Error condition message
Critical | -- ^ Critical condition messages
Alert | -- ^ Indication that action must be taken
Emergency -- ^ Indication that the system is unusable
deriving (Eq, Ord, Read, Show)
-- | Used by logging implementations only. Contains information about the log
-- message.
-- TODO: Add date information?
data LogMessage = LogMessage { logMessageString :: String
, logMessageLevel :: LogLevel
, logMessageContext :: Maybe (ModuleName,
FunctionName) }
-- | Used by logging implementations only. Provides a Logger object, given a
-- looping function operating on a 'LogMessage' channel.
logger :: (Chan (Maybe LogMessage) -> IO ()) -> IO Logger
logger l =
do c <- newChan
forkIO $ l c
return Logger { loggerLog = loggerLog_ c
, loggerStop = loggerStop_ c }
-- Stops the logger. This action is asynchronous.
loggerStop_ :: Chan (Maybe LogMessage) -> IO ()
loggerStop_ c = writeChan c Nothing
-- Logs a debug message. Debug messages are the least significant messages.
loggerLog_ :: Chan (Maybe LogMessage) -> Maybe (ModuleName, FunctionName) ->
LogLevel -> String -> IO ()
loggerLog_ c x l s =
do writeChan c $ Just (toLogMessage x l s)
return ()
-- Function to wrap a string and a log level into a LogMessage record.
toLogMessage :: Maybe (ModuleName, FunctionName) -> LogLevel -> String ->
LogMessage
toLogMessage x l s = LogMessage { logMessageContext = x
, logMessageLevel = l
, logMessageString = s }