31 , flushingStderrLogger
44import Control.Lens hiding (censoring)
45import Control.Logger.Internal
46import Control.Logger.Orphans ()
47import Control.Monad.Catch
48import qualified Data.List as List
50import Data.Text (Text)
51import qualified Data.Text as Text
54import Katip (ToObject (..))
55import System.Log.FastLogger
56import Text.Shakespeare.Text (st)
57-- import Control.Monad.RWS (censor)
58#if MIN_VERSION_mtl(2,3,0)
60import Control.Monad.IO.Class
67logError msg = withFrozenCallStack (logMsg Error msg)
73logDebug msg = withFrozenCallStack (logMsg Debug msg)
79logInfo msg = withFrozenCallStack (logMsg Info msg)
85logWarn msg = withFrozenCallStack (logMsg Warn msg)
88 :: (MonadIO m, HasCallStack)
92logInfoWith logger msg = withFrozenCallStack (logMsgWith logger Info msg)
95 :: (MonadIO m, HasCallStack)
99logDebugWith logger msg = withFrozenCallStack (logMsgWith logger Debug msg)
102 :: (MonadIO m, HasCallStack)
106logWarnWith logger msg = withFrozenCallStack (logMsgWith logger Warn msg)
109 :: (MonadIO m, HasCallStack)
113logErrorWith logger msg = withFrozenCallStack (logMsgWith logger Error msg)
115safeReplace :: Text -> Text -> Text -> Text
116safeReplace what with where_
117 | Text.null what = where_
118 | otherwise = Text.replace what with where_
120-- | Add a some text to scrubber
121censorWith :: Text -> Text -> Logger -> Logger
122censorWith replacement needle l =
123 l & scrubber <>~ Endo (safeReplace needle replacement)
125-- | Censor with "***"
126censor :: Text -> Logger -> Logger
127censor = censorWith "***"
129-- | Run an action with adjusted scrubber
131 :: forall r m a. (Has Logger r, MonadReader r m)
132 => (Endo Text -> Endo Text)
135withScrubber scrubF = local expandScrubber
137 expandScrubber :: r -> r
138 expandScrubber = over part (over scrubber scrubF)
140-- | Run an action while censoring additional text from logs
142 :: (Has Logger r, MonadReader r m)
147censoringWith replacement txt = withScrubber (<> censored)
149 censored = Endo (safeReplace txt replacement)
151-- | Run an action while censoring additional text from logs
153 :: (Has Logger r, MonadReader r m)
157censoring = censoringWith "***"
159-- | Log exceptions occured in computation and just ignore them.
161 :: (MonadIO m, MonadCatch m, Has Logger r, MonadReader r m)
164tryLogError a = try a >>= \case
165 Left (e :: SomeException) -> logError . Text.pack $ show e
169 :: (MonadIO m, MonadCatch m, Has Logger r, MonadReader r m)
172 -- ^ generates error message from exception type + exception text
174tryJustLog action genMsg = do
176 logAll :: SomeException -> Maybe SomeException
178 errorHandler (SomeException e) =
179 logError (genMsg $ Text.pack $ show e) >> pure Nothing
180 catchJust logAll (Just <$> action) errorHandler
183 :: (MonadIO m, Has Logger r, MonadCatch m, MonadReader r m)
186 -- ^ generates warning message from exception type + exception text
188tryJustWarn action genMsg = do
190 logAll :: SomeException -> Maybe SomeException
192 errorHandler (SomeException e) =
193 logWarn (genMsg $ Text.pack $ show e) >> pure Nothing
194 catchJust logAll (Just <$> action) errorHandler
196logExceptions :: (MonadCatch m, MonadThrow m, LoggingMonad r m) => m a -> m a
197logExceptions ma = catch ma $ \e -> do
198 logError $ (Text.pack . show) (e :: SomeException)
201oneoffLog :: MonadIO m => Logger -> LogSeverity -> Text -> m ()
202oneoffLog logger s t =
203 withFrozenCallStack (flip runReaderT logger $ logMsg s t)
205fileLogger :: MonadIO m => FilePath -> m Logger
206fileLogger fp = fastFunc <$> liftIO (newFileLoggerSet defaultBufSize fp)
208silentLogger :: Logger
209silentLogger = Logger mempty mempty (\_ _ _ _ -> return ())
211-- | Logger which flushes buffer after each message. This is useful with
214 :: LogSeverity -> LoggerSet -> Logger
215flushingFastFunc minLogLevel loggerSet =
216 Logger mempty mempty $ \_ stack logLevel msg ->
217 when (logLevel >= minLogLevel) $ do
220 $ formatLogStr ts stack mempty logLevel (toLogStr msg)
221 flushLogStr loggerSet
223-- | Used only in tests.
224stderrLogger :: MonadIO m => LogSource -> m Logger
226 defaultFastFunc loc Debug <$> liftIO (newStderrLoggerSet defaultBufSize)
228stdoutLogger :: MonadIO m => LogSource -> m Logger
230 defaultFastFunc loc Debug <$> liftIO (newStdoutLoggerSet defaultBufSize)
232-- | same as 'stderrLogger' but flushes buffer after each line.
233flushingStderrLogger :: MonadIO m => m Logger
234flushingStderrLogger =
235 flushingFastFunc Debug <$> liftIO (newStderrLoggerSet defaultBufSize)
237-- | Make our outdated 'Logger' of fast-logger's 'LoggerSet'
238fastFunc :: LoggerSet -> Logger
240 Logger mempty mempty $ \_ _ _ msg -> pushLogStr loggerSet $ toLogStr msg
244-- | Default logger tests and same things.
245defaultFastFunc :: LogSource -> LogSeverity -> LoggerSet -> Logger
246defaultFastFunc loc minLogLevel loggerSet =
247 Logger mempty mempty $ \_ stack s msg -> when (s >= minLogLevel) $ do
249 pushLogStr loggerSet $ formatLogStr ts stack loc s (toLogStr msg)
251-- | Prepends to 'LogStr' string with "[time][log-level]". Used for
254 :: UTCTime -> CallStack -> LogSource -> LogSeverity -> LogStr -> LogStr
255formatLogStr ts _ src level msg =
256 "[" <> tsStr <> "][" <> levelStr <> srcStr <> "] " <> msg <> "\n"
258 srcStr = if Text.null src then mempty else "#" <> toLogStr src
259 -- TODO: time-1.8 support padding: %6Q (microseconds)
260 tsStr = toLogStr $ formatTime defaultTimeLocale "%FT%T%Q" ts
261 levelStr = case level of
267compactCallStack :: CallStack -> String
270 . List.intersperse "->"
271 . map (\(f, l) -> f <> " (" <> compactLoc l <> ")")
273 where compactLoc loc = srcLocFile loc <> ":" <> show (srcLocStartLine loc)
275parseLogLevel :: Text -> Either String LogSeverity
276parseLogLevel t = case Text.strip t of
277 "debug" -> pure Debug
280 "error" -> pure Error
282 "Unreadable log level. Possible values: debug, info, warn and error"
284renderLogLevel :: LogSeverity -> Text
285renderLogLevel = \case
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list