gdritter repos bock / 303a9bb
Add logging messages and a die function Getty Ritter 5 years ago
2 changed file(s) with 39 addition(s) and 3 deletion(s). Collapse all Expand all
99 Log.warn ["warning-level message"]
1010 Log.error ["error-level message"]
1111 Log.critical ["critical-level message"]
12 Log.die ["critical-level message that exits the program"]
44 , warn
55 , error
66 , critical
7 , die
78
89 , Logger
910 , Level(..)
10 , setLogger
11 , HasLogger(..)
12 , setGlobalLogger
1113 , mkLogger
1214 ) where
1315
1719 import qualified Data.IORef as IORef
1820 import qualified GHC.Stack as GHC
1921 import qualified System.Environment as Env
22 import qualified System.Exit as Exit
2023 import qualified System.IO as IO
2124 import qualified System.IO.Unsafe as Unsafe
2225 import Prelude hiding (log, error)
2326
2427 import Logging.Bock.Color (supportsColor)
2528
29 -- | A 'Logger' represents the current configuration of log messages,
30 -- and includes where to send log messages (e.g. to stderr or to
31 -- files) and the current severity cutoff.
2632 data Logger = Logger
2733 { logUseColors :: !Bool
2834 , logWrite :: !(String -> IO ())
2935 , logLevel :: !Level
3036 }
3137
38 -- | The level of severity of the log. Severity levels are used for
39 -- controlling which logging messages are important enough to be shown
40 -- and which should not be. The default severity level of the logger
41 -- is 'Info', which means all messages except 'Debug' messages will be
42 -- shown. This can be modified upwards (to show only more important
43 -- messages) or downwards (to show all messages.)
3244 data Level
3345 = Debug
3446 | Info
3749 | Critical
3850 deriving (Eq, Show, Ord)
3951
52 -- | The default logger will
4053 parseLevel :: String -> Maybe Level
4154 parseLevel s = case map Char.toUpper s of
4255 "DEBUG" -> Just Debug
8093 Nothing -> pure IO.stderr
8194 IORef.newIORef logger
8295
83 setLogger :: Logger -> IO ()
84 setLogger = IORef.writeIORef defaultLogger
96 -- | Modify the current global logger.
97 setGlobalLogger :: Logger -> IO ()
98 setGlobalLogger = IORef.writeIORef defaultLogger
8599
100 -- | Create a logger with a specified severity cutoff and a handle to
101 -- write to. This will automatically support message coloring if the
102 -- handle corresponds to a TTY (i.e. if it is pointed at
103 -- stdout/stderr) and otherwise will not.
86104 mkLogger :: Level -> IO.Handle -> IO Logger
87105 mkLogger level h = do
88106 useColors <- supportsColor h
92110 , logLevel = level
93111 }
94112
113 -- | A typeclass for monads which support producing log
114 -- messages. These can piggyback on the IO instance, which uses a
115 -- shared global logger, or they can create a derived and locally
116 -- stored logger which might put its log messages in a different place
117 -- or use a different format
95118 class IOClass.MonadIO m => HasLogger m where
96119 getLogger :: m Logger
97120
112135 logWrite l endColorCode
113136 logWrite l "\n"
114137
138 -- | Produce a 'Debug'-level log message.
115139 debug :: (GHC.HasCallStack, HasLogger m) => [String] -> m ()
116140 debug = log Debug (getLoc GHC.callStack)
117141
142 -- | Produce an 'Info'-level log message.
118143 info :: (GHC.HasCallStack, HasLogger m) => [String] -> m ()
119144 info = log Info (getLoc GHC.callStack)
120145
146 -- | Produce an 'Warn'-level log message.
121147 warn :: (GHC.HasCallStack, HasLogger m) => [String] -> m ()
122148 warn = log Warn (getLoc GHC.callStack)
123149
150 -- | Produce an 'Error'-level log message.
124151 error :: (GHC.HasCallStack, HasLogger m) => [String] -> m ()
125152 error = log Error (getLoc GHC.callStack)
126153
154 -- | Produce a 'Critical'-level log message.
127155 critical :: (GHC.HasCallStack, HasLogger m) => [String] -> m ()
128156 critical = log Critical (getLoc GHC.callStack)
157
158 -- | Produce a 'Critical'-level log message, and then exit the program
159 -- immediately with an error code.
160 die :: (GHC.HasCallStack, HasLogger m) => [String] -> m ()
161 die msg = do
162 log Critical (getLoc GHC.callStack) msg
163 IOClass.liftIO Exit.exitFailure