module Ganeti.Logging
( setupLogging
, MonadLog(..)
, Priority(..)
, logDebug
, logInfo
, logNotice
, logWarning
, logError
, logCritical
, logAlert
, logEmergency
, SyslogUsage(..)
, syslogUsageToRaw
, syslogUsageFromRaw
) where
import Control.Monad
import Control.Monad.Reader
import System.Log.Logger
import System.Log.Handler.Simple
import System.Log.Handler.Syslog
import System.Log.Handler (setFormatter, LogHandler)
import System.Log.Formatter
import System.IO
import Ganeti.THH
import qualified Ganeti.ConstantUtils as ConstantUtils
$(declareLADT ''String "SyslogUsage"
[ ("SyslogNo", "no")
, ("SyslogYes", "yes")
, ("SyslogOnly", "only")
])
logFormatter :: String
-> Bool
-> Bool
-> LogFormatter a
logFormatter prog mt syslog =
let parts = [ if syslog
then "[$pid]:"
else "$time: " ++ prog ++ " pid=$pid"
, if mt then if syslog then " ($tid)" else "/$tid"
else ""
, " $prio $msg"
]
in tfLogFormatter "%F %X,%q %Z" $ concat parts
openFormattedHandler :: (LogHandler a) => Bool
-> LogFormatter a -> IO a -> IO [a]
openFormattedHandler False _ _ = return []
openFormattedHandler True fmt opener = do
handler <- opener
return [setFormatter handler fmt]
setupLogging :: Maybe String
-> String
-> Bool
-> Bool
-> Bool
-> SyslogUsage
-> IO ()
setupLogging logf program debug stderr_logging console syslog = do
let level = if debug then DEBUG else INFO
destf = if console then Just ConstantUtils.devConsole else logf
fmt = logFormatter program False False
file_logging = syslog /= SyslogOnly
updateGlobalLogger rootLoggerName (setLevel level)
stderr_handlers <- openFormattedHandler stderr_logging fmt $
streamHandler stderr level
file_handlers <- case destf of
Nothing -> return []
Just path -> openFormattedHandler file_logging fmt $
fileHandler path level
let handlers = file_handlers ++ stderr_handlers
updateGlobalLogger rootLoggerName $ setHandlers handlers
when (syslog /= SyslogNo) $ do
syslog_handler <- openlog program [PID] DAEMON INFO
updateGlobalLogger rootLoggerName $ addHandler syslog_handler
class Monad m => MonadLog m where
logAt :: Priority -> String -> m ()
instance MonadLog IO where
logAt = logM rootLoggerName
instance (MonadLog m) => MonadLog (ReaderT r m) where
logAt p x = lift $ logAt p x
logDebug :: (MonadLog m) => String -> m ()
logDebug = logAt DEBUG
logInfo :: (MonadLog m) => String -> m ()
logInfo = logAt INFO
logNotice :: (MonadLog m) => String -> m ()
logNotice = logAt NOTICE
logWarning :: (MonadLog m) => String -> m ()
logWarning = logAt WARNING
logError :: (MonadLog m) => String -> m ()
logError = logAt ERROR
logCritical :: (MonadLog m) => String -> m ()
logCritical = logAt CRITICAL
logAlert :: (MonadLog m) => String -> m ()
logAlert = logAt ALERT
logEmergency :: (MonadLog m) => String -> m ()
logEmergency = logAt EMERGENCY