htools: add logging functionality
[ganeti-local] / htools / Ganeti / Logging.hs
1 {-| Implementation of the Ganeti logging functionality.
2
3 This currently lacks the following (FIXME):
4
5 - syslog logging
6 - handling of the three-state syslog yes/no/only
7 - log file reopening
8
9 Note that this requires the hslogger library version 1.1 and above.
10
11 -}
12
13 {-
14
15 Copyright (C) 2011 Google Inc.
16
17 This program is free software; you can redistribute it and/or modify
18 it under the terms of the GNU General Public License as published by
19 the Free Software Foundation; either version 2 of the License, or
20 (at your option) any later version.
21
22 This program is distributed in the hope that it will be useful, but
23 WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25 General Public License for more details.
26
27 You should have received a copy of the GNU General Public License
28 along with this program; if not, write to the Free Software
29 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
30 02110-1301, USA.
31
32 -}
33
34 module Ganeti.Logging
35   ( setupLogging
36   , logDebug
37   , logInfo
38   , logNotice
39   , logWarning
40   , logError
41   , logCritical
42   , logAlert
43   , logEmergency
44   ) where
45
46 import System.Log.Logger
47 import System.Log.Handler.Simple
48 import System.Log.Handler (setFormatter)
49 import System.Log.Formatter
50 import System.IO
51
52 import qualified Ganeti.Constants as C
53
54 -- | Builds the log formatter.
55 logFormatter :: String  -- ^ Program
56              -> Bool    -- ^ Multithreaded
57              -> Bool    -- ^ Syslog
58              -> LogFormatter a
59 logFormatter prog mt syslog =
60   let parts = [ if syslog
61                   then "[$pid]:"
62                   else "$time: " ++ prog ++ " pid=$pid"
63               , if mt then if syslog then " ($tid)" else "/$tid"
64                   else ""
65               , " $prio $msg"
66               ]
67   in simpleLogFormatter $ concat parts
68
69 -- | Sets up the logging configuration.
70 setupLogging :: String    -- ^ Log file
71              -> String    -- ^ Program name
72              -> Bool      -- ^ Debug level
73              -> Bool      -- ^ Log to stderr
74              -> Bool      -- ^ Log to console
75              -> IO ()
76 setupLogging logf program debug stderr_logging console = do
77   let level = if debug then DEBUG else INFO
78       destf = if console then C.devConsole else logf
79       fmt = logFormatter program False False
80
81   updateGlobalLogger rootLoggerName (setLevel level)
82
83   stderr_handlers <-  if stderr_logging
84                         then do
85                           stderr_handler <- streamHandler stderr level
86                           return [setFormatter stderr_handler fmt]
87                         else return []
88   file_handler <- fileHandler destf level
89   let handlers = setFormatter file_handler fmt:stderr_handlers
90   updateGlobalLogger rootLoggerName $ setHandlers handlers
91
92 -- * Logging function aliases
93
94 -- | Log at debug level.
95 logDebug :: String -> IO ()
96 logDebug = debugM rootLoggerName
97
98 -- | Log at info level.
99 logInfo :: String -> IO ()
100 logInfo = infoM rootLoggerName
101
102 -- | Log at notice level.
103 logNotice :: String -> IO ()
104 logNotice = noticeM rootLoggerName
105
106 -- | Log at warning level.
107 logWarning :: String -> IO ()
108 logWarning = warningM rootLoggerName
109
110 -- | Log at error level.
111 logError :: String -> IO ()
112 logError = errorM rootLoggerName
113
114 -- | Log at critical level.
115 logCritical :: String -> IO ()
116 logCritical = criticalM rootLoggerName
117
118 -- | Log at alert level.
119 logAlert :: String -> IO ()
120 logAlert = alertM rootLoggerName
121
122 -- | Log at emergency level.
123 logEmergency :: String -> IO ()
124 logEmergency = emergencyM rootLoggerName