@@ -2,6 +2,9 @@
22module Control.Logger
33 ( Logger
44 , loggerContext
5+ , scrubber
6+ , censor
7+ , censorWith
58 , logMsg
69 , logMsgWith
710 , logInfo
@@ -32,13 +35,18 @@ module Control.Logger
3235 , compactCallStack
3336 , st
3437 , ToObject(..)
38+ , withScrubber
39+ , censoringWith
40+ , censoring
3541 ) where
3642
3743import Control.Has
44+import Control.Lens hiding (censoring)
3845import Control.Logger.Internal
3946import Control.Logger.Orphans ()
4047import Control.Monad.Catch
4148import qualified Data.List as List
49+import Data.Monoid
4250import Data.Text (Text)
4351import qualified Data.Text as Text
4452import Data.Time
@@ -46,6 +54,7 @@ import GHC.Stack
4654import Katip (ToObject (..))
4755import System.Log.FastLogger
4856import Text.Shakespeare.Text (st)
57+-- import Control.Monad.RWS (censor)
4958#if MIN_VERSION_mtl(2,3,0)
5059import Control.Monad
5160import Control.Monad.IO.Class
@@ -103,6 +112,50 @@ logErrorWith
103112 -> m ()
104113logErrorWith logger msg = withFrozenCallStack (logMsgWith logger Error msg)
105114
115+safeReplace :: Text -> Text -> Text -> Text
116+safeReplace what with where_
117+ | Text.null what = where_
118+ | otherwise = Text.replace what with where_
119+
120+-- | Add a some text to scrubber
121+censorWith :: Text -> Text -> Logger -> Logger
122+censorWith replacement needle l =
123+ l & scrubber <>~ Endo (safeReplace needle replacement)
124+
125+-- | Censor with "***"
126+censor :: Text -> Logger -> Logger
127+censor = censorWith "***"
128+
129+-- | Run an action with adjusted scrubber
130+withScrubber
131+ :: forall r m a. (Has Logger r, MonadReader r m)
132+ => (Endo Text -> Endo Text)
133+ -> m a
134+ -> m a
135+withScrubber scrubF = local expandScrubber
136+ where
137+ expandScrubber :: r -> r
138+ expandScrubber = over part (over scrubber scrubF)
139+
140+-- | Run an action while censoring additional text from logs
141+censoringWith
142+ :: (Has Logger r, MonadReader r m)
143+ => Text
144+ -> Text
145+ -> m a
146+ -> m a
147+censoringWith replacement txt = withScrubber (<> censored)
148+ where
149+ censored = Endo (safeReplace txt replacement)
150+
151+-- | Run an action while censoring additional text from logs
152+censoring
153+ :: (Has Logger r, MonadReader r m)
154+ => Text
155+ -> m a
156+ -> m a
157+censoring = censoringWith "***"
158+
106159-- | Log exceptions occured in computation and just ignore them.
107160tryLogError
108161 :: (MonadIO m, MonadCatch m, Has Logger r, MonadReader r m)
@@ -153,14 +206,14 @@ fileLogger :: MonadIO m => FilePath -> m Logger
153206fileLogger fp = fastFunc <$> liftIO (newFileLoggerSet defaultBufSize fp)
154207
155208silentLogger :: Logger
156−silentLogger = Logger mempty (\_ _ _ _ -> return ())
209+silentLogger = Logger mempty mempty (\_ _ _ _ -> return ())
157210
158211-- | Logger which flushes buffer after each message. This is useful with
159212-- stderrLogger.
160213flushingFastFunc
161214 :: LogSeverity -> LoggerSet -> Logger
162215flushingFastFunc minLogLevel loggerSet =
163− Logger mempty $ \_ stack logLevel msg ->
216+ Logger mempty mempty $ \_ stack logLevel msg ->
164217 when (logLevel >= minLogLevel) $ do
165218 ts <- getCurrentTime
166219 pushLogStr loggerSet
@@ -184,14 +237,14 @@ flushingStderrLogger =
184237-- | Make our outdated 'Logger' of fast-logger's 'LoggerSet'
185238fastFunc :: LoggerSet -> Logger
186239fastFunc loggerSet =
187− Logger mempty $ \_ _ _ msg -> pushLogStr loggerSet $ toLogStr msg
240+ Logger mempty mempty $ \_ _ _ msg -> pushLogStr loggerSet $ toLogStr msg
188241
189242type LogSource = Text
190243
191244-- | Default logger tests and same things.
192245defaultFastFunc :: LogSource -> LogSeverity -> LoggerSet -> Logger
193246defaultFastFunc loc minLogLevel loggerSet =
194− Logger mempty $ \_ stack s msg -> when (s >= minLogLevel) $ do
247+ Logger mempty mempty $ \_ stack s msg -> when (s >= minLogLevel) $ do
195248 ts <- getCurrentTime
196249 pushLogStr loggerSet $ formatLogStr ts stack loc s (toLogStr msg)
197250