|
1 |
{-# LANGUAGE TemplateHaskell #-}
|
|
2 |
|
1 |
3 |
{-| Implementation of the Ganeti logging functionality.
|
2 |
4 |
|
3 |
5 |
This currently lacks the following (FIXME):
|
4 |
6 |
|
5 |
|
- syslog logging
|
6 |
|
- handling of the three-state syslog yes/no/only
|
7 |
7 |
- log file reopening
|
8 |
8 |
|
9 |
9 |
Note that this requires the hslogger library version 1.1 and above.
|
... | ... | |
12 |
12 |
|
13 |
13 |
{-
|
14 |
14 |
|
15 |
|
Copyright (C) 2011 Google Inc.
|
|
15 |
Copyright (C) 2011, 2012 Google Inc.
|
16 |
16 |
|
17 |
17 |
This program is free software; you can redistribute it and/or modify
|
18 |
18 |
it under the terms of the GNU General Public License as published by
|
... | ... | |
41 |
41 |
, logCritical
|
42 |
42 |
, logAlert
|
43 |
43 |
, logEmergency
|
|
44 |
, SyslogUsage(..)
|
|
45 |
, syslogUsageToRaw
|
|
46 |
, syslogUsageFromRaw
|
44 |
47 |
) where
|
45 |
48 |
|
|
49 |
import Control.Monad (when)
|
46 |
50 |
import System.Log.Logger
|
47 |
51 |
import System.Log.Handler.Simple
|
48 |
|
import System.Log.Handler (setFormatter)
|
|
52 |
import System.Log.Handler.Syslog
|
|
53 |
import System.Log.Handler (setFormatter, LogHandler)
|
49 |
54 |
import System.Log.Formatter
|
50 |
55 |
import System.IO
|
51 |
56 |
|
|
57 |
import Ganeti.THH
|
52 |
58 |
import qualified Ganeti.Constants as C
|
53 |
59 |
|
|
60 |
-- | Syslog usage type.
|
|
61 |
$(declareSADT "SyslogUsage"
|
|
62 |
[ ("SyslogNo", 'C.syslogNo)
|
|
63 |
, ("SyslogYes", 'C.syslogYes)
|
|
64 |
, ("SyslogOnly", 'C.syslogOnly)
|
|
65 |
])
|
|
66 |
|
54 |
67 |
-- | Builds the log formatter.
|
55 |
68 |
logFormatter :: String -- ^ Program
|
56 |
69 |
-> Bool -- ^ Multithreaded
|
... | ... | |
66 |
79 |
]
|
67 |
80 |
in simpleLogFormatter $ concat parts
|
68 |
81 |
|
|
82 |
-- | Helper to open and set the formatter on a log if enabled by a
|
|
83 |
-- given condition, otherwise returning an empty list.
|
|
84 |
openFormattedHandler :: (LogHandler a) => Bool
|
|
85 |
-> LogFormatter a -> IO a -> IO [a]
|
|
86 |
openFormattedHandler False _ _ = return []
|
|
87 |
openFormattedHandler True fmt opener = do
|
|
88 |
handler <- opener
|
|
89 |
return [setFormatter handler fmt]
|
|
90 |
|
69 |
91 |
-- | Sets up the logging configuration.
|
70 |
92 |
setupLogging :: String -- ^ Log file
|
71 |
93 |
-> String -- ^ Program name
|
72 |
94 |
-> Bool -- ^ Debug level
|
73 |
95 |
-> Bool -- ^ Log to stderr
|
74 |
96 |
-> Bool -- ^ Log to console
|
|
97 |
-> SyslogUsage -- ^ Syslog usage
|
75 |
98 |
-> IO ()
|
76 |
|
setupLogging logf program debug stderr_logging console = do
|
|
99 |
setupLogging logf program debug stderr_logging console syslog = do
|
77 |
100 |
let level = if debug then DEBUG else INFO
|
78 |
101 |
destf = if console then C.devConsole else logf
|
79 |
102 |
fmt = logFormatter program False False
|
80 |
103 |
|
81 |
104 |
updateGlobalLogger rootLoggerName (setLevel level)
|
82 |
105 |
|
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
|
|
106 |
stderr_handlers <- openFormattedHandler stderr_logging fmt $
|
|
107 |
streamHandler stderr level
|
|
108 |
|
|
109 |
file_handlers <- openFormattedHandler (syslog /= SyslogOnly) fmt $
|
|
110 |
fileHandler destf level
|
|
111 |
|
|
112 |
let handlers = concat [file_handlers, stderr_handlers]
|
90 |
113 |
updateGlobalLogger rootLoggerName $ setHandlers handlers
|
|
114 |
-- syslog handler is special (another type, still instance of the
|
|
115 |
-- typeclass, and has a built-in formatter), so we can't pass it in
|
|
116 |
-- the above list
|
|
117 |
when (syslog /= SyslogNo) $ do
|
|
118 |
syslog_handler <- openlog program [PID] DAEMON INFO
|
|
119 |
updateGlobalLogger rootLoggerName $ addHandler syslog_handler
|
91 |
120 |
|
92 |
121 |
-- * Logging function aliases
|
93 |
122 |
|