{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UnicodeSyntax #-}
module System.Logger.Logger.Internal
(
LoggerConfig(..)
, loggerConfigQueueSize
, loggerConfigThreshold
, loggerConfigScope
, loggerConfigPolicy
, loggerConfigExceptionLimit
, loggerConfigExceptionWait
, loggerConfigExitTimeout
, defaultLoggerConfig
, validateLoggerConfig
, pLoggerConfig
, pLoggerConfig_
, Logger
, loggerScope
, loggerThreshold
, createLogger
, createLogger_
, releaseLogger
, withLogger
, withLogger_
, loggCtx
, withLogFunction
, withLogFunction_
, LoggerT
, runLoggerT
, runLogT
) where
import Configuration.Utils hiding (Error, Lens')
import Control.Concurrent (threadDelay)
import Control.Concurrent.Async
import Control.DeepSeq
import Control.Exception.Enclosed
import Control.Exception.Lifted
import Control.Monad.Except
import Control.Monad.Trans.Control
import Control.Monad.Unicode
import Data.IORef
import Data.Monoid.Unicode
import qualified Data.Text as T
import qualified Data.Text.IO as T (hPutStrLn)
import Data.Typeable
import Data.Void
import GHC.Generics
import GHC.IORef
import Lens.Micro
import Numeric.Natural
import Prelude.Unicode
import System.Clock
import System.IO (stderr)
import System.Timeout
import System.Logger.Internal
import System.Logger.Internal.Queue
import System.Logger.Types
data LoggerConfig = LoggerConfig
{ LoggerConfig -> Natural
_loggerConfigQueueSize ∷ !Natural
, LoggerConfig -> LogLevel
_loggerConfigThreshold ∷ !LogLevel
, LoggerConfig -> LogScope
_loggerConfigScope ∷ !LogScope
, LoggerConfig -> LogPolicy
_loggerConfigPolicy ∷ !LogPolicy
, LoggerConfig -> Maybe Natural
_loggerConfigExceptionLimit ∷ !(Maybe Natural)
, LoggerConfig -> Maybe Natural
_loggerConfigExceptionWait ∷ !(Maybe Natural)
, LoggerConfig -> Maybe Natural
_loggerConfigExitTimeout ∷ !(Maybe Natural)
}
deriving (Int -> LoggerConfig -> ShowS
[LoggerConfig] -> ShowS
LoggerConfig -> String
(Int -> LoggerConfig -> ShowS)
-> (LoggerConfig -> String)
-> ([LoggerConfig] -> ShowS)
-> Show LoggerConfig
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [LoggerConfig] -> ShowS
$cshowList :: [LoggerConfig] -> ShowS
show :: LoggerConfig -> String
$cshow :: LoggerConfig -> String
showsPrec :: Int -> LoggerConfig -> ShowS
$cshowsPrec :: Int -> LoggerConfig -> ShowS
Show, ReadPrec [LoggerConfig]
ReadPrec LoggerConfig
Int -> ReadS LoggerConfig
ReadS [LoggerConfig]
(Int -> ReadS LoggerConfig)
-> ReadS [LoggerConfig]
-> ReadPrec LoggerConfig
-> ReadPrec [LoggerConfig]
-> Read LoggerConfig
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [LoggerConfig]
$creadListPrec :: ReadPrec [LoggerConfig]
readPrec :: ReadPrec LoggerConfig
$creadPrec :: ReadPrec LoggerConfig
readList :: ReadS [LoggerConfig]
$creadList :: ReadS [LoggerConfig]
readsPrec :: Int -> ReadS LoggerConfig
$creadsPrec :: Int -> ReadS LoggerConfig
Read, LoggerConfig -> LoggerConfig -> Bool
(LoggerConfig -> LoggerConfig -> Bool)
-> (LoggerConfig -> LoggerConfig -> Bool) -> Eq LoggerConfig
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: LoggerConfig -> LoggerConfig -> Bool
$c/= :: LoggerConfig -> LoggerConfig -> Bool
== :: LoggerConfig -> LoggerConfig -> Bool
$c== :: LoggerConfig -> LoggerConfig -> Bool
Eq, Eq LoggerConfig
Eq LoggerConfig
-> (LoggerConfig -> LoggerConfig -> Ordering)
-> (LoggerConfig -> LoggerConfig -> Bool)
-> (LoggerConfig -> LoggerConfig -> Bool)
-> (LoggerConfig -> LoggerConfig -> Bool)
-> (LoggerConfig -> LoggerConfig -> Bool)
-> (LoggerConfig -> LoggerConfig -> LoggerConfig)
-> (LoggerConfig -> LoggerConfig -> LoggerConfig)
-> Ord LoggerConfig
LoggerConfig -> LoggerConfig -> Bool
LoggerConfig -> LoggerConfig -> Ordering
LoggerConfig -> LoggerConfig -> LoggerConfig
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: LoggerConfig -> LoggerConfig -> LoggerConfig
$cmin :: LoggerConfig -> LoggerConfig -> LoggerConfig
max :: LoggerConfig -> LoggerConfig -> LoggerConfig
$cmax :: LoggerConfig -> LoggerConfig -> LoggerConfig
>= :: LoggerConfig -> LoggerConfig -> Bool
$c>= :: LoggerConfig -> LoggerConfig -> Bool
> :: LoggerConfig -> LoggerConfig -> Bool
$c> :: LoggerConfig -> LoggerConfig -> Bool
<= :: LoggerConfig -> LoggerConfig -> Bool
$c<= :: LoggerConfig -> LoggerConfig -> Bool
< :: LoggerConfig -> LoggerConfig -> Bool
$c< :: LoggerConfig -> LoggerConfig -> Bool
compare :: LoggerConfig -> LoggerConfig -> Ordering
$ccompare :: LoggerConfig -> LoggerConfig -> Ordering
$cp1Ord :: Eq LoggerConfig
Ord, Typeable, (forall x. LoggerConfig -> Rep LoggerConfig x)
-> (forall x. Rep LoggerConfig x -> LoggerConfig)
-> Generic LoggerConfig
forall x. Rep LoggerConfig x -> LoggerConfig
forall x. LoggerConfig -> Rep LoggerConfig x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep LoggerConfig x -> LoggerConfig
$cfrom :: forall x. LoggerConfig -> Rep LoggerConfig x
Generic)
loggerConfigQueueSize ∷ Lens' LoggerConfig Natural
loggerConfigQueueSize :: (Natural -> f Natural) -> LoggerConfig -> f LoggerConfig
loggerConfigQueueSize = (LoggerConfig -> Natural)
-> (LoggerConfig -> Natural -> LoggerConfig)
-> Lens LoggerConfig LoggerConfig Natural Natural
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens LoggerConfig -> Natural
_loggerConfigQueueSize ((LoggerConfig -> Natural -> LoggerConfig)
-> Lens LoggerConfig LoggerConfig Natural Natural)
-> (LoggerConfig -> Natural -> LoggerConfig)
-> Lens LoggerConfig LoggerConfig Natural Natural
forall a b. (a -> b) -> a -> b
$ \LoggerConfig
a Natural
b → LoggerConfig
a { _loggerConfigQueueSize :: Natural
_loggerConfigQueueSize = Natural
b }
loggerConfigThreshold ∷ Lens' LoggerConfig LogLevel
loggerConfigThreshold :: (LogLevel -> f LogLevel) -> LoggerConfig -> f LoggerConfig
loggerConfigThreshold = (LoggerConfig -> LogLevel)
-> (LoggerConfig -> LogLevel -> LoggerConfig)
-> Lens LoggerConfig LoggerConfig LogLevel LogLevel
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens LoggerConfig -> LogLevel
_loggerConfigThreshold ((LoggerConfig -> LogLevel -> LoggerConfig)
-> Lens LoggerConfig LoggerConfig LogLevel LogLevel)
-> (LoggerConfig -> LogLevel -> LoggerConfig)
-> Lens LoggerConfig LoggerConfig LogLevel LogLevel
forall a b. (a -> b) -> a -> b
$ \LoggerConfig
a LogLevel
b → LoggerConfig
a { _loggerConfigThreshold :: LogLevel
_loggerConfigThreshold = LogLevel
b }
loggerConfigScope ∷ Lens' LoggerConfig LogScope
loggerConfigScope :: (LogScope -> f LogScope) -> LoggerConfig -> f LoggerConfig
loggerConfigScope = (LoggerConfig -> LogScope)
-> (LoggerConfig -> LogScope -> LoggerConfig)
-> Lens LoggerConfig LoggerConfig LogScope LogScope
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens LoggerConfig -> LogScope
_loggerConfigScope ((LoggerConfig -> LogScope -> LoggerConfig)
-> Lens LoggerConfig LoggerConfig LogScope LogScope)
-> (LoggerConfig -> LogScope -> LoggerConfig)
-> Lens LoggerConfig LoggerConfig LogScope LogScope
forall a b. (a -> b) -> a -> b
$ \LoggerConfig
a LogScope
b → LoggerConfig
a { _loggerConfigScope :: LogScope
_loggerConfigScope = LogScope
b }
loggerConfigPolicy ∷ Lens' LoggerConfig LogPolicy
loggerConfigPolicy :: (LogPolicy -> f LogPolicy) -> LoggerConfig -> f LoggerConfig
loggerConfigPolicy = (LoggerConfig -> LogPolicy)
-> (LoggerConfig -> LogPolicy -> LoggerConfig)
-> Lens LoggerConfig LoggerConfig LogPolicy LogPolicy
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens LoggerConfig -> LogPolicy
_loggerConfigPolicy ((LoggerConfig -> LogPolicy -> LoggerConfig)
-> Lens LoggerConfig LoggerConfig LogPolicy LogPolicy)
-> (LoggerConfig -> LogPolicy -> LoggerConfig)
-> Lens LoggerConfig LoggerConfig LogPolicy LogPolicy
forall a b. (a -> b) -> a -> b
$ \LoggerConfig
a LogPolicy
b → LoggerConfig
a { _loggerConfigPolicy :: LogPolicy
_loggerConfigPolicy = LogPolicy
b }
loggerConfigExceptionLimit ∷ Lens' LoggerConfig (Maybe Natural)
loggerConfigExceptionLimit :: (Maybe Natural -> f (Maybe Natural))
-> LoggerConfig -> f LoggerConfig
loggerConfigExceptionLimit = (LoggerConfig -> Maybe Natural)
-> (LoggerConfig -> Maybe Natural -> LoggerConfig)
-> Lens LoggerConfig LoggerConfig (Maybe Natural) (Maybe Natural)
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens LoggerConfig -> Maybe Natural
_loggerConfigExceptionLimit ((LoggerConfig -> Maybe Natural -> LoggerConfig)
-> Lens LoggerConfig LoggerConfig (Maybe Natural) (Maybe Natural))
-> (LoggerConfig -> Maybe Natural -> LoggerConfig)
-> Lens LoggerConfig LoggerConfig (Maybe Natural) (Maybe Natural)
forall a b. (a -> b) -> a -> b
$ \LoggerConfig
a Maybe Natural
b → LoggerConfig
a { _loggerConfigExceptionLimit :: Maybe Natural
_loggerConfigExceptionLimit = Maybe Natural
b }
loggerConfigExceptionWait ∷ Lens' LoggerConfig (Maybe Natural)
loggerConfigExceptionWait :: (Maybe Natural -> f (Maybe Natural))
-> LoggerConfig -> f LoggerConfig
loggerConfigExceptionWait = (LoggerConfig -> Maybe Natural)
-> (LoggerConfig -> Maybe Natural -> LoggerConfig)
-> Lens LoggerConfig LoggerConfig (Maybe Natural) (Maybe Natural)
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens LoggerConfig -> Maybe Natural
_loggerConfigExceptionWait ((LoggerConfig -> Maybe Natural -> LoggerConfig)
-> Lens LoggerConfig LoggerConfig (Maybe Natural) (Maybe Natural))
-> (LoggerConfig -> Maybe Natural -> LoggerConfig)
-> Lens LoggerConfig LoggerConfig (Maybe Natural) (Maybe Natural)
forall a b. (a -> b) -> a -> b
$ \LoggerConfig
a Maybe Natural
b → LoggerConfig
a { _loggerConfigExceptionWait :: Maybe Natural
_loggerConfigExceptionWait = Maybe Natural
b }
loggerConfigExitTimeout ∷ Lens' LoggerConfig (Maybe Natural)
loggerConfigExitTimeout :: (Maybe Natural -> f (Maybe Natural))
-> LoggerConfig -> f LoggerConfig
loggerConfigExitTimeout = (LoggerConfig -> Maybe Natural)
-> (LoggerConfig -> Maybe Natural -> LoggerConfig)
-> Lens LoggerConfig LoggerConfig (Maybe Natural) (Maybe Natural)
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens LoggerConfig -> Maybe Natural
_loggerConfigExitTimeout ((LoggerConfig -> Maybe Natural -> LoggerConfig)
-> Lens LoggerConfig LoggerConfig (Maybe Natural) (Maybe Natural))
-> (LoggerConfig -> Maybe Natural -> LoggerConfig)
-> Lens LoggerConfig LoggerConfig (Maybe Natural) (Maybe Natural)
forall a b. (a -> b) -> a -> b
$ \LoggerConfig
a Maybe Natural
b → LoggerConfig
a { _loggerConfigExitTimeout :: Maybe Natural
_loggerConfigExitTimeout = Maybe Natural
b }
instance NFData LoggerConfig
defaultLoggerConfig ∷ LoggerConfig
defaultLoggerConfig :: LoggerConfig
defaultLoggerConfig = LoggerConfig :: Natural
-> LogLevel
-> LogScope
-> LogPolicy
-> Maybe Natural
-> Maybe Natural
-> Maybe Natural
-> LoggerConfig
LoggerConfig
{ _loggerConfigQueueSize :: Natural
_loggerConfigQueueSize = Natural
1000
, _loggerConfigThreshold :: LogLevel
_loggerConfigThreshold = LogLevel
Warn
, _loggerConfigScope :: LogScope
_loggerConfigScope = []
, _loggerConfigPolicy :: LogPolicy
_loggerConfigPolicy = LogPolicy
LogPolicyDiscard
, _loggerConfigExceptionLimit :: Maybe Natural
_loggerConfigExceptionLimit = Natural -> Maybe Natural
forall a. a -> Maybe a
Just Natural
10
, _loggerConfigExceptionWait :: Maybe Natural
_loggerConfigExceptionWait = Natural -> Maybe Natural
forall a. a -> Maybe a
Just Natural
1000
, _loggerConfigExitTimeout :: Maybe Natural
_loggerConfigExitTimeout = Natural -> Maybe Natural
forall a. a -> Maybe a
Just Natural
1000000
}
validateLoggerConfig ∷ ConfigValidation LoggerConfig λ
validateLoggerConfig :: LoggerConfig -> m ()
validateLoggerConfig LoggerConfig
_ = () -> m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
instance ToJSON LoggerConfig where
toJSON :: LoggerConfig -> Value
toJSON LoggerConfig{Natural
LogScope
Maybe Natural
LogPolicy
LogLevel
_loggerConfigExitTimeout :: Maybe Natural
_loggerConfigExceptionWait :: Maybe Natural
_loggerConfigExceptionLimit :: Maybe Natural
_loggerConfigPolicy :: LogPolicy
_loggerConfigScope :: LogScope
_loggerConfigThreshold :: LogLevel
_loggerConfigQueueSize :: Natural
_loggerConfigExitTimeout :: LoggerConfig -> Maybe Natural
_loggerConfigExceptionWait :: LoggerConfig -> Maybe Natural
_loggerConfigExceptionLimit :: LoggerConfig -> Maybe Natural
_loggerConfigPolicy :: LoggerConfig -> LogPolicy
_loggerConfigScope :: LoggerConfig -> LogScope
_loggerConfigThreshold :: LoggerConfig -> LogLevel
_loggerConfigQueueSize :: LoggerConfig -> Natural
..} = [Pair] -> Value
object
[ Key
"queue_size" Key -> Natural -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Natural
_loggerConfigQueueSize
, Key
"log_level" Key -> LogLevel -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= LogLevel
_loggerConfigThreshold
, Key
"scope" Key -> LogScope -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= LogScope
_loggerConfigScope
, Key
"policy" Key -> LogPolicy -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= LogPolicy
_loggerConfigPolicy
, Key
"exception_limit" Key -> Maybe Natural -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Maybe Natural
_loggerConfigExceptionLimit
, Key
"exception_wait" Key -> Maybe Natural -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Maybe Natural
_loggerConfigExceptionWait
, Key
"exit_timeout" Key -> Maybe Natural -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Maybe Natural
_loggerConfigExitTimeout
]
instance FromJSON (LoggerConfig → LoggerConfig) where
parseJSON :: Value -> Parser (LoggerConfig -> LoggerConfig)
parseJSON = String
-> (Object -> Parser (LoggerConfig -> LoggerConfig))
-> Value
-> Parser (LoggerConfig -> LoggerConfig)
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"LoggerConfig" ((Object -> Parser (LoggerConfig -> LoggerConfig))
-> Value -> Parser (LoggerConfig -> LoggerConfig))
-> (Object -> Parser (LoggerConfig -> LoggerConfig))
-> Value
-> Parser (LoggerConfig -> LoggerConfig)
forall a b. (a -> b) -> a -> b
$ \Object
o → LoggerConfig -> LoggerConfig
forall a. a -> a
id
(LoggerConfig -> LoggerConfig)
-> Parser (LoggerConfig -> LoggerConfig)
-> Parser (LoggerConfig -> LoggerConfig)
forall (f :: * -> *) b c a.
Functor f =>
(b -> c) -> f (a -> b) -> f (a -> c)
<$< Lens LoggerConfig LoggerConfig Natural Natural
loggerConfigQueueSize Lens LoggerConfig LoggerConfig Natural Natural
-> Text -> Object -> Parser (LoggerConfig -> LoggerConfig)
forall b a.
FromJSON b =>
Lens' a b -> Text -> Object -> Parser (a -> a)
..: Text
"queue_size" (Object -> Parser (LoggerConfig -> LoggerConfig))
-> Object -> Parser (LoggerConfig -> LoggerConfig)
forall a b. (a -> b) -> a -> b
% Object
o
Parser (LoggerConfig -> LoggerConfig)
-> Parser (LoggerConfig -> LoggerConfig)
-> Parser (LoggerConfig -> LoggerConfig)
forall (f :: * -> *) b c a.
Applicative f =>
f (b -> c) -> f (a -> b) -> f (a -> c)
<*< Lens LoggerConfig LoggerConfig LogLevel LogLevel
loggerConfigThreshold Lens LoggerConfig LoggerConfig LogLevel LogLevel
-> Text -> Object -> Parser (LoggerConfig -> LoggerConfig)
forall b a.
FromJSON b =>
Lens' a b -> Text -> Object -> Parser (a -> a)
..: Text
"log_level" (Object -> Parser (LoggerConfig -> LoggerConfig))
-> Object -> Parser (LoggerConfig -> LoggerConfig)
forall a b. (a -> b) -> a -> b
% Object
o
Parser (LoggerConfig -> LoggerConfig)
-> Parser (LoggerConfig -> LoggerConfig)
-> Parser (LoggerConfig -> LoggerConfig)
forall (f :: * -> *) b c a.
Applicative f =>
f (b -> c) -> f (a -> b) -> f (a -> c)
<*< Lens LoggerConfig LoggerConfig LogScope LogScope
loggerConfigScope Lens LoggerConfig LoggerConfig LogScope LogScope
-> Text -> Object -> Parser (LoggerConfig -> LoggerConfig)
forall b a.
FromJSON b =>
Lens' a b -> Text -> Object -> Parser (a -> a)
..: Text
"scope" (Object -> Parser (LoggerConfig -> LoggerConfig))
-> Object -> Parser (LoggerConfig -> LoggerConfig)
forall a b. (a -> b) -> a -> b
% Object
o
Parser (LoggerConfig -> LoggerConfig)
-> Parser (LoggerConfig -> LoggerConfig)
-> Parser (LoggerConfig -> LoggerConfig)
forall (f :: * -> *) b c a.
Applicative f =>
f (b -> c) -> f (a -> b) -> f (a -> c)
<*< Lens LoggerConfig LoggerConfig LogPolicy LogPolicy
loggerConfigPolicy Lens LoggerConfig LoggerConfig LogPolicy LogPolicy
-> Text -> Object -> Parser (LoggerConfig -> LoggerConfig)
forall b a.
FromJSON b =>
Lens' a b -> Text -> Object -> Parser (a -> a)
..: Text
"policy" (Object -> Parser (LoggerConfig -> LoggerConfig))
-> Object -> Parser (LoggerConfig -> LoggerConfig)
forall a b. (a -> b) -> a -> b
% Object
o
Parser (LoggerConfig -> LoggerConfig)
-> Parser (LoggerConfig -> LoggerConfig)
-> Parser (LoggerConfig -> LoggerConfig)
forall (f :: * -> *) b c a.
Applicative f =>
f (b -> c) -> f (a -> b) -> f (a -> c)
<*< Lens LoggerConfig LoggerConfig (Maybe Natural) (Maybe Natural)
loggerConfigExceptionLimit Lens LoggerConfig LoggerConfig (Maybe Natural) (Maybe Natural)
-> Text -> Object -> Parser (LoggerConfig -> LoggerConfig)
forall b a.
FromJSON b =>
Lens' a b -> Text -> Object -> Parser (a -> a)
..: Text
"exception_limit" (Object -> Parser (LoggerConfig -> LoggerConfig))
-> Object -> Parser (LoggerConfig -> LoggerConfig)
forall a b. (a -> b) -> a -> b
% Object
o
Parser (LoggerConfig -> LoggerConfig)
-> Parser (LoggerConfig -> LoggerConfig)
-> Parser (LoggerConfig -> LoggerConfig)
forall (f :: * -> *) b c a.
Applicative f =>
f (b -> c) -> f (a -> b) -> f (a -> c)
<*< Lens LoggerConfig LoggerConfig (Maybe Natural) (Maybe Natural)
loggerConfigExceptionWait Lens LoggerConfig LoggerConfig (Maybe Natural) (Maybe Natural)
-> Text -> Object -> Parser (LoggerConfig -> LoggerConfig)
forall b a.
FromJSON b =>
Lens' a b -> Text -> Object -> Parser (a -> a)
..: Text
"exception_wait" (Object -> Parser (LoggerConfig -> LoggerConfig))
-> Object -> Parser (LoggerConfig -> LoggerConfig)
forall a b. (a -> b) -> a -> b
% Object
o
Parser (LoggerConfig -> LoggerConfig)
-> Parser (LoggerConfig -> LoggerConfig)
-> Parser (LoggerConfig -> LoggerConfig)
forall (f :: * -> *) b c a.
Applicative f =>
f (b -> c) -> f (a -> b) -> f (a -> c)
<*< Lens LoggerConfig LoggerConfig (Maybe Natural) (Maybe Natural)
loggerConfigExitTimeout Lens LoggerConfig LoggerConfig (Maybe Natural) (Maybe Natural)
-> Text -> Object -> Parser (LoggerConfig -> LoggerConfig)
forall b a.
FromJSON b =>
Lens' a b -> Text -> Object -> Parser (a -> a)
..: Text
"exit_timeout" (Object -> Parser (LoggerConfig -> LoggerConfig))
-> Object -> Parser (LoggerConfig -> LoggerConfig)
forall a b. (a -> b) -> a -> b
% Object
o
pLoggerConfig ∷ MParser LoggerConfig
pLoggerConfig :: MParser LoggerConfig
pLoggerConfig = Text -> MParser LoggerConfig
pLoggerConfig_ Text
""
pLoggerConfig_
∷ T.Text
→ MParser LoggerConfig
pLoggerConfig_ :: Text -> MParser LoggerConfig
pLoggerConfig_ Text
prefix = LoggerConfig -> LoggerConfig
forall a. a -> a
id
(LoggerConfig -> LoggerConfig)
-> MParser LoggerConfig -> MParser LoggerConfig
forall (f :: * -> *) b c a.
Functor f =>
(b -> c) -> f (a -> b) -> f (a -> c)
<$< Lens LoggerConfig LoggerConfig Natural Natural
loggerConfigQueueSize Lens LoggerConfig LoggerConfig Natural Natural
-> Parser Natural -> MParser LoggerConfig
forall (f :: * -> *) a b.
(Alternative f, Applicative f) =>
Lens' a b -> f b -> f (a -> a)
.:: ReadM Natural -> Mod OptionFields Natural -> Parser Natural
forall a. ReadM a -> Mod OptionFields a -> Parser a
option ReadM Natural
forall a. Read a => ReadM a
auto
(Mod OptionFields Natural -> Parser Natural)
-> Mod OptionFields Natural -> Parser Natural
forall a b. (a -> b) -> a -> b
% String -> Mod OptionFields Natural
forall (f :: * -> *) a. HasName f => String -> Mod f a
long (Text -> String
T.unpack Text
prefix String -> ShowS
forall α. Monoid α => α -> α -> α
⊕ String
"queue-size")
Mod OptionFields Natural
-> Mod OptionFields Natural -> Mod OptionFields Natural
forall α. Monoid α => α -> α -> α
⊕ String -> Mod OptionFields Natural
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"INT"
Mod OptionFields Natural
-> Mod OptionFields Natural -> Mod OptionFields Natural
forall α. Monoid α => α -> α -> α
⊕ String -> Mod OptionFields Natural
forall (f :: * -> *) a. String -> Mod f a
help String
"size of the internal logger queue"
MParser LoggerConfig
-> MParser LoggerConfig -> MParser LoggerConfig
forall (f :: * -> *) b c a.
Applicative f =>
f (b -> c) -> f (a -> b) -> f (a -> c)
<*< Lens LoggerConfig LoggerConfig LogLevel LogLevel
loggerConfigThreshold Lens LoggerConfig LoggerConfig LogLevel LogLevel
-> Parser LogLevel -> MParser LoggerConfig
forall (f :: * -> *) a b.
(Alternative f, Applicative f) =>
Lens' a b -> f b -> f (a -> a)
.:: Text -> Parser LogLevel
pLogLevel_ Text
prefix
MParser LoggerConfig
-> MParser LoggerConfig -> MParser LoggerConfig
forall (f :: * -> *) b c a.
Applicative f =>
f (b -> c) -> f (a -> b) -> f (a -> c)
<*< Lens LoggerConfig LoggerConfig LogPolicy LogPolicy
loggerConfigPolicy Lens LoggerConfig LoggerConfig LogPolicy LogPolicy
-> Parser LogPolicy -> MParser LoggerConfig
forall (f :: * -> *) a b.
(Alternative f, Applicative f) =>
Lens' a b -> f b -> f (a -> a)
.:: Text -> Parser LogPolicy
pLogPolicy_ Text
prefix
MParser LoggerConfig
-> MParser LoggerConfig -> MParser LoggerConfig
forall (f :: * -> *) b c a.
Applicative f =>
f (b -> c) -> f (a -> b) -> f (a -> c)
<*< Lens LoggerConfig LoggerConfig (Maybe Natural) (Maybe Natural)
loggerConfigExceptionLimit Lens LoggerConfig LoggerConfig (Maybe Natural) (Maybe Natural)
-> Parser (Maybe Natural) -> MParser LoggerConfig
forall (f :: * -> *) a b.
(Alternative f, Applicative f) =>
Lens' a b -> f b -> f (a -> a)
.:: (Natural -> Maybe Natural)
-> Parser Natural -> Parser (Maybe Natural)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Natural -> Maybe Natural
forall a. a -> Maybe a
Just (Parser Natural -> Parser (Maybe Natural))
-> Parser Natural -> Parser (Maybe Natural)
forall a b. (a -> b) -> a -> b
% ReadM Natural -> Mod OptionFields Natural -> Parser Natural
forall a. ReadM a -> Mod OptionFields a -> Parser a
option ReadM Natural
forall a. Read a => ReadM a
auto
(Mod OptionFields Natural -> Parser Natural)
-> Mod OptionFields Natural -> Parser Natural
forall a b. (a -> b) -> a -> b
% String -> Mod OptionFields Natural
forall (f :: * -> *) a. HasName f => String -> Mod f a
long (Text -> String
T.unpack Text
prefix String -> ShowS
forall α. Monoid α => α -> α -> α
⊕ String
"exception-limit")
Mod OptionFields Natural
-> Mod OptionFields Natural -> Mod OptionFields Natural
forall α. Monoid α => α -> α -> α
⊕ String -> Mod OptionFields Natural
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"INT"
Mod OptionFields Natural
-> Mod OptionFields Natural -> Mod OptionFields Natural
forall α. Monoid α => α -> α -> α
⊕ String -> Mod OptionFields Natural
forall (f :: * -> *) a. String -> Mod f a
help String
"maximal number of backend failures before and exception is raised"
MParser LoggerConfig
-> MParser LoggerConfig -> MParser LoggerConfig
forall (f :: * -> *) b c a.
Applicative f =>
f (b -> c) -> f (a -> b) -> f (a -> c)
<*< Lens LoggerConfig LoggerConfig (Maybe Natural) (Maybe Natural)
loggerConfigExceptionWait Lens LoggerConfig LoggerConfig (Maybe Natural) (Maybe Natural)
-> Parser (Maybe Natural) -> MParser LoggerConfig
forall (f :: * -> *) a b.
(Alternative f, Applicative f) =>
Lens' a b -> f b -> f (a -> a)
.:: (Natural -> Maybe Natural)
-> Parser Natural -> Parser (Maybe Natural)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Natural -> Maybe Natural
forall a. a -> Maybe a
Just (Parser Natural -> Parser (Maybe Natural))
-> Parser Natural -> Parser (Maybe Natural)
forall a b. (a -> b) -> a -> b
% ReadM Natural -> Mod OptionFields Natural -> Parser Natural
forall a. ReadM a -> Mod OptionFields a -> Parser a
option ReadM Natural
forall a. Read a => ReadM a
auto
(Mod OptionFields Natural -> Parser Natural)
-> Mod OptionFields Natural -> Parser Natural
forall a b. (a -> b) -> a -> b
% String -> Mod OptionFields Natural
forall (f :: * -> *) a. HasName f => String -> Mod f a
long (Text -> String
T.unpack Text
prefix String -> ShowS
forall α. Monoid α => α -> α -> α
⊕ String
"exception-wait")
Mod OptionFields Natural
-> Mod OptionFields Natural -> Mod OptionFields Natural
forall α. Monoid α => α -> α -> α
⊕ String -> Mod OptionFields Natural
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"INT"
Mod OptionFields Natural
-> Mod OptionFields Natural -> Mod OptionFields Natural
forall α. Monoid α => α -> α -> α
⊕ String -> Mod OptionFields Natural
forall (f :: * -> *) a. String -> Mod f a
help String
"time to wait after an backend failure occured"
MParser LoggerConfig
-> MParser LoggerConfig -> MParser LoggerConfig
forall (f :: * -> *) b c a.
Applicative f =>
f (b -> c) -> f (a -> b) -> f (a -> c)
<*< Lens LoggerConfig LoggerConfig (Maybe Natural) (Maybe Natural)
loggerConfigExitTimeout Lens LoggerConfig LoggerConfig (Maybe Natural) (Maybe Natural)
-> Parser (Maybe Natural) -> MParser LoggerConfig
forall (f :: * -> *) a b.
(Alternative f, Applicative f) =>
Lens' a b -> f b -> f (a -> a)
.:: (Natural -> Maybe Natural)
-> Parser Natural -> Parser (Maybe Natural)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Natural -> Maybe Natural
forall a. a -> Maybe a
Just (Parser Natural -> Parser (Maybe Natural))
-> Parser Natural -> Parser (Maybe Natural)
forall a b. (a -> b) -> a -> b
% ReadM Natural -> Mod OptionFields Natural -> Parser Natural
forall a. ReadM a -> Mod OptionFields a -> Parser a
option ReadM Natural
forall a. Read a => ReadM a
auto
(Mod OptionFields Natural -> Parser Natural)
-> Mod OptionFields Natural -> Parser Natural
forall a b. (a -> b) -> a -> b
% String -> Mod OptionFields Natural
forall (f :: * -> *) a. HasName f => String -> Mod f a
long (Text -> String
T.unpack Text
prefix String -> ShowS
forall α. Monoid α => α -> α -> α
⊕ String
"exit-timeout")
Mod OptionFields Natural
-> Mod OptionFields Natural -> Mod OptionFields Natural
forall α. Monoid α => α -> α -> α
⊕ String -> Mod OptionFields Natural
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"INT"
Mod OptionFields Natural
-> Mod OptionFields Natural -> Mod OptionFields Natural
forall α. Monoid α => α -> α -> α
⊕ String -> Mod OptionFields Natural
forall (f :: * -> *) a. String -> Mod f a
help String
"timeout for flushing the log message queue on exit"
#ifdef USE_TBMQUEUE
type LoggerQueue a = TBMQueue (LogMessage a)
#else
type LoggerQueue a = TBMChan (LogMessage a)
#endif
data Logger a = Logger
{ Logger a -> LoggerQueue a
_loggerQueue ∷ !(LoggerQueue a)
, Logger a -> Async ()
_loggerWorker ∷ !(Async ())
, Logger a -> LogLevel
_loggerThreshold ∷ !LogLevel
, Logger a -> LogScope
_loggerScope ∷ !LogScope
, Logger a -> LogPolicy
_loggerPolicy ∷ !LogPolicy
, Logger a -> IORef Natural
_loggerMissed ∷ !(IORef Natural)
, Logger a -> Maybe Natural
_loggerExitTimeout ∷ !(Maybe Natural)
, Logger a -> Text -> IO ()
_loggerErrLogFunction ∷ !(T.Text → IO ())
}
deriving (Typeable, (forall x. Logger a -> Rep (Logger a) x)
-> (forall x. Rep (Logger a) x -> Logger a) -> Generic (Logger a)
forall x. Rep (Logger a) x -> Logger a
forall x. Logger a -> Rep (Logger a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (Logger a) x -> Logger a
forall a x. Logger a -> Rep (Logger a) x
$cto :: forall a x. Rep (Logger a) x -> Logger a
$cfrom :: forall a x. Logger a -> Rep (Logger a) x
Generic)
loggerThreshold ∷ Lens' (Logger a) LogLevel
loggerThreshold :: (LogLevel -> f LogLevel) -> Logger a -> f (Logger a)
loggerThreshold = (Logger a -> LogLevel)
-> (Logger a -> LogLevel -> Logger a)
-> Lens (Logger a) (Logger a) LogLevel LogLevel
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens Logger a -> LogLevel
forall a. Logger a -> LogLevel
_loggerThreshold ((Logger a -> LogLevel -> Logger a)
-> Lens (Logger a) (Logger a) LogLevel LogLevel)
-> (Logger a -> LogLevel -> Logger a)
-> Lens (Logger a) (Logger a) LogLevel LogLevel
forall a b. (a -> b) -> a -> b
$ \Logger a
a LogLevel
b → Logger a
a { _loggerThreshold :: LogLevel
_loggerThreshold = LogLevel
b }
{-# INLINE loggerThreshold #-}
loggerScope ∷ Lens' (Logger a) LogScope
loggerScope :: (LogScope -> f LogScope) -> Logger a -> f (Logger a)
loggerScope = (Logger a -> LogScope)
-> (Logger a -> LogScope -> Logger a)
-> Lens (Logger a) (Logger a) LogScope LogScope
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens Logger a -> LogScope
forall a. Logger a -> LogScope
_loggerScope ((Logger a -> LogScope -> Logger a)
-> Lens (Logger a) (Logger a) LogScope LogScope)
-> (Logger a -> LogScope -> Logger a)
-> Lens (Logger a) (Logger a) LogScope LogScope
forall a b. (a -> b) -> a -> b
$ \Logger a
a LogScope
b → Logger a
a { _loggerScope :: LogScope
_loggerScope = LogScope
b }
{-# INLINE loggerScope #-}
loggerPolicy ∷ Lens' (Logger a) LogPolicy
loggerPolicy :: (LogPolicy -> f LogPolicy) -> Logger a -> f (Logger a)
loggerPolicy = (Logger a -> LogPolicy)
-> (Logger a -> LogPolicy -> Logger a)
-> Lens (Logger a) (Logger a) LogPolicy LogPolicy
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens Logger a -> LogPolicy
forall a. Logger a -> LogPolicy
_loggerPolicy ((Logger a -> LogPolicy -> Logger a)
-> Lens (Logger a) (Logger a) LogPolicy LogPolicy)
-> (Logger a -> LogPolicy -> Logger a)
-> Lens (Logger a) (Logger a) LogPolicy LogPolicy
forall a b. (a -> b) -> a -> b
$ \Logger a
a LogPolicy
b → Logger a
a { _loggerPolicy :: LogPolicy
_loggerPolicy = LogPolicy
b }
{-# INLINE loggerPolicy #-}
createLogger
∷ MonadIO μ
⇒ LoggerConfig
→ LoggerBackend a
→ μ (Logger a)
createLogger :: LoggerConfig -> LoggerBackend a -> μ (Logger a)
createLogger = (Text -> IO ()) -> LoggerConfig -> LoggerBackend a -> μ (Logger a)
forall (μ :: * -> *) a.
MonadIO μ =>
(Text -> IO ()) -> LoggerConfig -> LoggerBackend a -> μ (Logger a)
createLogger_ (Handle -> Text -> IO ()
T.hPutStrLn Handle
stderr)
createLogger_
∷ MonadIO μ
⇒ (T.Text → IO ())
→ LoggerConfig
→ LoggerBackend a
→ μ (Logger a)
createLogger_ :: (Text -> IO ()) -> LoggerConfig -> LoggerBackend a -> μ (Logger a)
createLogger_ Text -> IO ()
errLogFun LoggerConfig{Natural
LogScope
Maybe Natural
LogPolicy
LogLevel
_loggerConfigExitTimeout :: Maybe Natural
_loggerConfigExceptionWait :: Maybe Natural
_loggerConfigExceptionLimit :: Maybe Natural
_loggerConfigPolicy :: LogPolicy
_loggerConfigScope :: LogScope
_loggerConfigThreshold :: LogLevel
_loggerConfigQueueSize :: Natural
_loggerConfigExitTimeout :: LoggerConfig -> Maybe Natural
_loggerConfigExceptionWait :: LoggerConfig -> Maybe Natural
_loggerConfigExceptionLimit :: LoggerConfig -> Maybe Natural
_loggerConfigPolicy :: LoggerConfig -> LogPolicy
_loggerConfigScope :: LoggerConfig -> LogScope
_loggerConfigThreshold :: LoggerConfig -> LogLevel
_loggerConfigQueueSize :: LoggerConfig -> Natural
..} LoggerBackend a
backend = IO (Logger a) -> μ (Logger a)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Logger a) -> μ (Logger a)) -> IO (Logger a) -> μ (Logger a)
forall a b. (a -> b) -> a -> b
$ do
LoggerQueue a
queue ← Natural -> IO (LoggerQueue a)
forall q a. BoundedCloseableQueue q a => Natural -> IO q
newQueue (Natural -> Natural
forall a b. (Integral a, Num b) => a -> b
fromIntegral Natural
_loggerConfigQueueSize)
IORef Natural
missed ← Natural -> IO (IORef Natural)
forall a. a -> IO (IORef a)
newIORef Natural
0
Async ()
worker ← (Text -> IO ())
-> Maybe Natural
-> Maybe Natural
-> LoggerBackend a
-> LoggerQueue a
-> IORef Natural
-> IO (Async ())
forall a.
(Text -> IO ())
-> Maybe Natural
-> Maybe Natural
-> LoggerBackend a
-> LoggerQueue a
-> IORef Natural
-> IO (Async ())
backendWorker Text -> IO ()
errLogFun Maybe Natural
_loggerConfigExceptionLimit Maybe Natural
_loggerConfigExceptionWait LoggerBackend a
backend LoggerQueue a
queue IORef Natural
missed
Async () -> IO ()
forall a. Async a -> IO ()
link Async ()
worker
Logger a -> IO (Logger a)
forall (m :: * -> *) a. Monad m => a -> m a
return (Logger a -> IO (Logger a)) -> Logger a -> IO (Logger a)
forall a b. (a -> b) -> a -> b
$ Logger :: forall a.
LoggerQueue a
-> Async ()
-> LogLevel
-> LogScope
-> LogPolicy
-> IORef Natural
-> Maybe Natural
-> (Text -> IO ())
-> Logger a
Logger
{ _loggerQueue :: LoggerQueue a
_loggerQueue = LoggerQueue a
queue
, _loggerWorker :: Async ()
_loggerWorker = Async ()
worker
, _loggerThreshold :: LogLevel
_loggerThreshold = LogLevel
_loggerConfigThreshold
, _loggerScope :: LogScope
_loggerScope = LogScope
_loggerConfigScope
, _loggerPolicy :: LogPolicy
_loggerPolicy = LogPolicy
_loggerConfigPolicy
, _loggerMissed :: IORef Natural
_loggerMissed = IORef Natural
missed
, _loggerExitTimeout :: Maybe Natural
_loggerExitTimeout = Maybe Natural
_loggerConfigExitTimeout
, _loggerErrLogFunction :: Text -> IO ()
_loggerErrLogFunction = Text -> IO ()
errLogFun
}
backendWorker
∷ (T.Text → IO ())
→ Maybe Natural
→ Maybe Natural
→ LoggerBackend a
→ LoggerQueue a
→ IORef Natural
→ IO (Async ())
backendWorker :: (Text -> IO ())
-> Maybe Natural
-> Maybe Natural
-> LoggerBackend a
-> LoggerQueue a
-> IORef Natural
-> IO (Async ())
backendWorker Text -> IO ()
errLogFun Maybe Natural
errLimit Maybe Natural
errWait LoggerBackend a
backend LoggerQueue a
queue IORef Natural
missed = IO (Async ()) -> IO (Async ())
forall (m :: * -> *) a. MonadBaseControl IO m => m a -> m a
mask_ (IO (Async ()) -> IO (Async ())) -> IO (Async ()) -> IO (Async ())
forall a b. (a -> b) -> a -> b
$
((forall b. IO b -> IO b) -> IO ()) -> IO (Async ())
forall a. ((forall b. IO b -> IO b) -> IO a) -> IO (Async a)
asyncWithUnmask (((forall b. IO b -> IO b) -> IO ()) -> IO (Async ()))
-> ((forall b. IO b -> IO b) -> IO ()) -> IO (Async ())
forall a b. (a -> b) -> a -> b
$ \forall b. IO b -> IO b
umask → IO () -> IO ()
forall b. IO b -> IO b
umask ([SomeException] -> IO ()
go []) IO () -> (LoggerKilled -> IO ()) -> IO ()
forall (m :: * -> *) e a.
(MonadBaseControl IO m, Exception e) =>
m a -> (e -> m a) -> m a
`catch` \(LoggerKilled
_ ∷ LoggerKilled) → () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
where
go :: [SomeException] -> IO ()
go [SomeException]
errList = do
TimeSpec
t ← Clock -> IO TimeSpec
getTime Clock
Realtime
TimeSpec -> IO (Maybe (Either (LogMessage Text) (LogMessage a)))
readMsg TimeSpec
t IO (Maybe (Either (LogMessage Text) (LogMessage a)))
-> (Maybe (Either (LogMessage Text) (LogMessage a)) -> IO ())
-> IO ()
forall (m :: * -> *) α β. Monad m => m α -> (α -> m β) -> m β
≫= \case
Maybe (Either (LogMessage Text) (LogMessage a))
Nothing → () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Just Either (LogMessage Text) (LogMessage a)
msg → [SomeException]
-> Either (LogMessage Text) (LogMessage a) -> IO [SomeException]
runBackend [SomeException]
errList Either (LogMessage Text) (LogMessage a)
msg IO [SomeException] -> ([SomeException] -> IO ()) -> IO ()
forall (m :: * -> *) α β. Monad m => m α -> (α -> m β) -> m β
≫= [SomeException] -> IO ()
go
runBackend :: [SomeException]
-> Either (LogMessage Text) (LogMessage a) -> IO [SomeException]
runBackend [SomeException]
errList Either (LogMessage Text) (LogMessage a)
msg = (LoggerBackend a
backend Either (LogMessage Text) (LogMessage a)
msg IO () -> IO [SomeException] -> IO [SomeException]
forall (m :: * -> *) α β. Monad m => m α -> m β -> m β
≫ [SomeException] -> IO [SomeException]
forall (m :: * -> *) a. Monad m => a -> m a
return []) IO [SomeException]
-> (SomeException -> IO [SomeException]) -> IO [SomeException]
forall (m :: * -> *) a.
MonadBaseControl IO m =>
m a -> (SomeException -> m a) -> m a
`catchAny` \SomeException
e → do
TimeSpec
t ← Clock -> IO TimeSpec
getTime Clock
Realtime
let errMsg :: LogMessage Text
errMsg = TimeSpec -> Text -> LogMessage Text
forall a. TimeSpec -> a -> LogMessage a
backendErrorMsg TimeSpec
t (SomeException -> Text
forall a b. (Show a, IsString b) => a -> b
sshow SomeException
e)
LoggerBackend a
backend (LogMessage Text -> Either (LogMessage Text) (LogMessage a)
forall a b. a -> Either a b
Left LogMessage Text
errMsg) IO () -> (SomeException -> IO ()) -> IO ()
forall (m :: * -> *) a.
MonadBaseControl IO m =>
m a -> (SomeException -> m a) -> m a
`catchAny` \SomeException
_ →
Text -> IO ()
errLogFun (LogMessage Text -> Text
errLogMsg LogMessage Text
errMsg) IO () -> (SomeException -> IO ()) -> IO ()
forall (m :: * -> *) a.
MonadBaseControl IO m =>
m a -> (SomeException -> m a) -> m a
`catchAny` \SomeException
_ →
() -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
case SomeException -> Maybe (LoggerException Void)
forall e. Exception e => SomeException -> Maybe e
fromException SomeException
e of
Just (BackendTerminatedException SomeException
_ ∷ LoggerException Void) → SomeException -> IO [SomeException]
forall (m :: * -> *) e a. (MonadBase IO m, Exception e) => e -> m a
throwIO SomeException
e
Maybe (LoggerException Void)
_ → do
IO () -> (Natural -> IO ()) -> Maybe Natural -> IO ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (() -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()) (Int -> IO ()
threadDelay (Int -> IO ()) -> (Natural -> Int) -> Natural -> IO ()
forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ Natural -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral) Maybe Natural
errWait
let errList' :: [SomeException]
errList' = SomeException
eSomeException -> [SomeException] -> [SomeException]
forall a. a -> [a] -> [a]
:[SomeException]
errList
case Maybe Natural
errLimit of
Maybe Natural
Nothing → [SomeException] -> IO [SomeException]
forall (m :: * -> *) a. Monad m => a -> m a
return []
Just Natural
n
| Int -> Natural
forall a b. (Integral a, Num b) => a -> b
fromIntegral ([SomeException] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [SomeException]
errList') Natural -> Natural -> Bool
forall a. Ord a => a -> a -> Bool
> Natural
n → LoggerException Void -> IO [SomeException]
forall (m :: * -> *) e a. (MonadBase IO m, Exception e) => e -> m a
throwIO (LoggerException Void -> IO [SomeException])
-> LoggerException Void -> IO [SomeException]
forall a b. (a -> b) -> a -> b
$ [SomeException] -> LoggerException Void
BackendTooManyExceptions ([SomeException] -> [SomeException]
forall a. [a] -> [a]
reverse [SomeException]
errList')
| Bool
otherwise → [SomeException] -> IO [SomeException]
forall (m :: * -> *) a. Monad m => a -> m a
return [SomeException]
errList'
readMsg :: TimeSpec -> IO (Maybe (Either (LogMessage Text) (LogMessage a)))
readMsg TimeSpec
t = do
Natural
n ← IORef Natural -> Natural -> IO Natural
forall a. IORef a -> a -> IO a
atomicSwapIORef IORef Natural
missed Natural
0
if Natural
n Natural -> Natural -> Bool
forall a. Ord a => a -> a -> Bool
> Natural
0
then do
Maybe (Either (LogMessage Text) (LogMessage a))
-> IO (Maybe (Either (LogMessage Text) (LogMessage a)))
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (Either (LogMessage Text) (LogMessage a))
-> IO (Maybe (Either (LogMessage Text) (LogMessage a))))
-> (LogMessage Text
-> Maybe (Either (LogMessage Text) (LogMessage a)))
-> LogMessage Text
-> IO (Maybe (Either (LogMessage Text) (LogMessage a)))
forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ Either (LogMessage Text) (LogMessage a)
-> Maybe (Either (LogMessage Text) (LogMessage a))
forall a. a -> Maybe a
Just (Either (LogMessage Text) (LogMessage a)
-> Maybe (Either (LogMessage Text) (LogMessage a)))
-> (LogMessage Text -> Either (LogMessage Text) (LogMessage a))
-> LogMessage Text
-> Maybe (Either (LogMessage Text) (LogMessage a))
forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ LogMessage Text -> Either (LogMessage Text) (LogMessage a)
forall a b. a -> Either a b
Left (LogMessage Text
-> IO (Maybe (Either (LogMessage Text) (LogMessage a))))
-> LogMessage Text
-> IO (Maybe (Either (LogMessage Text) (LogMessage a)))
forall a b. (a -> b) -> a -> b
$ TimeSpec -> Natural -> LogMessage Text
forall a a.
(Monoid a, IsString a, Show a) =>
TimeSpec -> a -> LogMessage a
discardMsg TimeSpec
t Natural
n
else
(LogMessage a -> Either (LogMessage Text) (LogMessage a))
-> Maybe (LogMessage a)
-> Maybe (Either (LogMessage Text) (LogMessage a))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap LogMessage a -> Either (LogMessage Text) (LogMessage a)
forall a b. b -> Either a b
Right (Maybe (LogMessage a)
-> Maybe (Either (LogMessage Text) (LogMessage a)))
-> IO (Maybe (LogMessage a))
-> IO (Maybe (Either (LogMessage Text) (LogMessage a)))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> LoggerQueue a -> IO (Maybe (LogMessage a))
forall q a. BoundedCloseableQueue q a => q -> IO (Maybe a)
readQueue LoggerQueue a
queue
discardMsg :: TimeSpec -> a -> LogMessage a
discardMsg TimeSpec
t a
n = LogMessage :: forall a. a -> LogLevel -> LogScope -> TimeSpec -> LogMessage a
LogMessage
{ _logMsg :: a
_logMsg = a
"discarded " a -> a -> a
forall α. Monoid α => α -> α -> α
⊕ a -> a
forall a b. (Show a, IsString b) => a -> b
sshow a
n a -> a -> a
forall α. Monoid α => α -> α -> α
⊕ a
" log messages"
, _logMsgLevel :: LogLevel
_logMsgLevel = LogLevel
Warn
, _logMsgScope :: LogScope
_logMsgScope = [(Text
"system", Text
"logger")]
, _logMsgTime :: TimeSpec
_logMsgTime = TimeSpec
t
}
backendErrorMsg :: TimeSpec -> a -> LogMessage a
backendErrorMsg TimeSpec
t a
e = LogMessage :: forall a. a -> LogLevel -> LogScope -> TimeSpec -> LogMessage a
LogMessage
{ _logMsg :: a
_logMsg = a
e
, _logMsgLevel :: LogLevel
_logMsgLevel = LogLevel
Error
, _logMsgScope :: LogScope
_logMsgScope = [(Text
"system", Text
"logger"), (Text
"component", Text
"backend")]
, _logMsgTime :: TimeSpec
_logMsgTime = TimeSpec
t
}
errLogMsg :: LogMessage Text -> Text
errLogMsg LogMessage{LogScope
Text
TimeSpec
LogLevel
_logMsgTime :: TimeSpec
_logMsgScope :: LogScope
_logMsgLevel :: LogLevel
_logMsg :: Text
_logMsgTime :: forall a. LogMessage a -> TimeSpec
_logMsgScope :: forall a. LogMessage a -> LogScope
_logMsgLevel :: forall a. LogMessage a -> LogLevel
_logMsg :: forall a. LogMessage a -> a
..} = [Text] -> Text
T.unwords
[ TimeSpec -> Text
forall a. IsString a => TimeSpec -> a
formatIso8601Milli TimeSpec
_logMsgTime
, Text
"[" Text -> Text -> Text
forall α. Monoid α => α -> α -> α
⊕ LogLevel -> Text
forall a. IsString a => LogLevel -> a
logLevelText LogLevel
_logMsgLevel Text -> Text -> Text
forall α. Monoid α => α -> α -> α
⊕ Text
"]"
, LogScope -> Text
formatScope LogScope
_logMsgScope
, Text
_logMsg
]
formatScope :: LogScope -> Text
formatScope LogScope
scope = Text
"[" Text -> Text -> Text
forall α. Monoid α => α -> α -> α
⊕ Text -> [Text] -> Text
T.intercalate Text
"," (((Text, Text) -> Text) -> LogScope -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map (Text, Text) -> Text
forall α. (Monoid α, IsString α) => (α, α) -> α
formatLabel LogScope
scope) Text -> Text -> Text
forall α. Monoid α => α -> α -> α
⊕ Text
"]"
formatLabel :: (α, α) -> α
formatLabel (α
k,α
v) = α
"(" α -> α -> α
forall α. Monoid α => α -> α -> α
⊕ α
k α -> α -> α
forall α. Monoid α => α -> α -> α
⊕ α
"," α -> α -> α
forall α. Monoid α => α -> α -> α
⊕ α
v α -> α -> α
forall α. Monoid α => α -> α -> α
⊕ α
")"
data LoggerKilled = LoggerKilled deriving (Int -> LoggerKilled -> ShowS
[LoggerKilled] -> ShowS
LoggerKilled -> String
(Int -> LoggerKilled -> ShowS)
-> (LoggerKilled -> String)
-> ([LoggerKilled] -> ShowS)
-> Show LoggerKilled
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [LoggerKilled] -> ShowS
$cshowList :: [LoggerKilled] -> ShowS
show :: LoggerKilled -> String
$cshow :: LoggerKilled -> String
showsPrec :: Int -> LoggerKilled -> ShowS
$cshowsPrec :: Int -> LoggerKilled -> ShowS
Show, Typeable)
instance Exception LoggerKilled
releaseLogger
∷ MonadIO μ
⇒ Logger a
→ μ ()
releaseLogger :: Logger a -> μ ()
releaseLogger Logger{LogScope
Maybe Natural
Async ()
IORef Natural
LoggerQueue a
LogPolicy
LogLevel
Text -> IO ()
_loggerErrLogFunction :: Text -> IO ()
_loggerExitTimeout :: Maybe Natural
_loggerMissed :: IORef Natural
_loggerPolicy :: LogPolicy
_loggerScope :: LogScope
_loggerThreshold :: LogLevel
_loggerWorker :: Async ()
_loggerQueue :: LoggerQueue a
_loggerErrLogFunction :: forall a. Logger a -> Text -> IO ()
_loggerExitTimeout :: forall a. Logger a -> Maybe Natural
_loggerMissed :: forall a. Logger a -> IORef Natural
_loggerPolicy :: forall a. Logger a -> LogPolicy
_loggerScope :: forall a. Logger a -> LogScope
_loggerThreshold :: forall a. Logger a -> LogLevel
_loggerWorker :: forall a. Logger a -> Async ()
_loggerQueue :: forall a. Logger a -> LoggerQueue a
..} = IO () -> μ ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> μ ()) -> IO () -> μ ()
forall a b. (a -> b) -> a -> b
$ do
LoggerQueue a -> IO ()
forall q a. BoundedCloseableQueue q a => q -> IO ()
closeQueue LoggerQueue a
_loggerQueue
Maybe ()
complete ← (IO () -> IO (Maybe ()))
-> (Natural -> IO () -> IO (Maybe ()))
-> Maybe Natural
-> IO ()
-> IO (Maybe ())
forall b a. b -> (a -> b) -> Maybe a -> b
maybe ((() -> Maybe ()) -> IO () -> IO (Maybe ())
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap () -> Maybe ()
forall a. a -> Maybe a
Just) (Int -> IO () -> IO (Maybe ())
forall a. Int -> IO a -> IO (Maybe a)
timeout (Int -> IO () -> IO (Maybe ()))
-> (Natural -> Int) -> Natural -> IO () -> IO (Maybe ())
forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ Natural -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral) Maybe Natural
_loggerExitTimeout (IO () -> IO (Maybe ())) -> IO () -> IO (Maybe ())
forall a b. (a -> b) -> a -> b
$ Async () -> IO ()
forall a. Async a -> IO a
wait Async ()
_loggerWorker
case Maybe ()
complete of
Maybe ()
Nothing → Text -> IO ()
_loggerErrLogFunction Text
"logger: timeout while flushing queue; remaining messages are discarded"
Just ()
_ → () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Async () -> LoggerKilled -> IO ()
forall e a. Exception e => Async a -> e -> IO ()
cancelWith Async ()
_loggerWorker LoggerKilled
LoggerKilled
withLogger
∷ (MonadIO μ, MonadBaseControl IO μ)
⇒ LoggerConfig
→ LoggerBackend a
→ (Logger a → μ α)
→ μ α
withLogger :: LoggerConfig -> LoggerBackend a -> (Logger a -> μ α) -> μ α
withLogger = (Text -> IO ())
-> LoggerConfig -> LoggerBackend a -> (Logger a -> μ α) -> μ α
forall (μ :: * -> *) a α.
(MonadIO μ, MonadBaseControl IO μ) =>
(Text -> IO ())
-> LoggerConfig -> LoggerBackend a -> (Logger a -> μ α) -> μ α
withLogger_ (Handle -> Text -> IO ()
T.hPutStrLn Handle
stderr)
withLogger_
∷ (MonadIO μ, MonadBaseControl IO μ)
⇒ (T.Text → IO ())
→ LoggerConfig
→ LoggerBackend a
→ (Logger a → μ α)
→ μ α
withLogger_ :: (Text -> IO ())
-> LoggerConfig -> LoggerBackend a -> (Logger a -> μ α) -> μ α
withLogger_ Text -> IO ()
errLogFun LoggerConfig
config LoggerBackend a
backend =
μ (Logger a) -> (Logger a -> μ ()) -> (Logger a -> μ α) -> μ α
forall (m :: * -> *) a b c.
MonadBaseControl IO m =>
m a -> (a -> m b) -> (a -> m c) -> m c
bracket ((Text -> IO ()) -> LoggerConfig -> LoggerBackend a -> μ (Logger a)
forall (μ :: * -> *) a.
MonadIO μ =>
(Text -> IO ()) -> LoggerConfig -> LoggerBackend a -> μ (Logger a)
createLogger_ Text -> IO ()
errLogFun LoggerConfig
config LoggerBackend a
backend) Logger a -> μ ()
forall (μ :: * -> *) a. MonadIO μ => Logger a -> μ ()
releaseLogger
withLogFunction
∷ (Show a, Typeable a, NFData a, MonadIO μ, MonadBaseControl IO μ)
⇒ LoggerConfig
→ LoggerBackend a
→ (LogFunctionIO a → μ α)
→ μ α
withLogFunction :: LoggerConfig -> LoggerBackend a -> (LogFunctionIO a -> μ α) -> μ α
withLogFunction = (Text -> IO ())
-> LoggerConfig
-> LoggerBackend a
-> (LogFunctionIO a -> μ α)
-> μ α
forall a (μ :: * -> *) α.
(Show a, Typeable a, NFData a, MonadIO μ, MonadBaseControl IO μ) =>
(Text -> IO ())
-> LoggerConfig
-> LoggerBackend a
-> (LogFunctionIO a -> μ α)
-> μ α
withLogFunction_ (Handle -> Text -> IO ()
T.hPutStrLn Handle
stderr)
withLogFunction_
∷ (Show a, Typeable a, NFData a, MonadIO μ, MonadBaseControl IO μ)
⇒ (T.Text → IO ())
→ LoggerConfig
→ LoggerBackend a
→ (LogFunctionIO a → μ α)
→ μ α
withLogFunction_ :: (Text -> IO ())
-> LoggerConfig
-> LoggerBackend a
-> (LogFunctionIO a -> μ α)
-> μ α
withLogFunction_ Text -> IO ()
errLogFun LoggerConfig
config LoggerBackend a
backend LogFunctionIO a -> μ α
f =
(Text -> IO ())
-> LoggerConfig -> LoggerBackend a -> (Logger a -> μ α) -> μ α
forall (μ :: * -> *) a α.
(MonadIO μ, MonadBaseControl IO μ) =>
(Text -> IO ())
-> LoggerConfig -> LoggerBackend a -> (Logger a -> μ α) -> μ α
withLogger_ Text -> IO ()
errLogFun LoggerConfig
config LoggerBackend a
backend ((Logger a -> μ α) -> μ α) -> (Logger a -> μ α) -> μ α
forall a b. (a -> b) -> a -> b
$ LogFunctionIO a -> μ α
f (LogFunctionIO a -> μ α)
-> (Logger a -> LogFunctionIO a) -> Logger a -> μ α
forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ Logger a -> LogFunctionIO a
forall a.
(Show a, Typeable a, NFData a) =>
Logger a -> LogFunctionIO a
loggCtx
loggCtx
∷ (Show a, Typeable a, NFData a)
⇒ Logger a
→ LogFunctionIO a
loggCtx :: Logger a -> LogFunctionIO a
loggCtx Logger{LogScope
Maybe Natural
Async ()
IORef Natural
LoggerQueue a
LogPolicy
LogLevel
Text -> IO ()
_loggerErrLogFunction :: Text -> IO ()
_loggerExitTimeout :: Maybe Natural
_loggerMissed :: IORef Natural
_loggerPolicy :: LogPolicy
_loggerScope :: LogScope
_loggerThreshold :: LogLevel
_loggerWorker :: Async ()
_loggerQueue :: LoggerQueue a
_loggerErrLogFunction :: forall a. Logger a -> Text -> IO ()
_loggerExitTimeout :: forall a. Logger a -> Maybe Natural
_loggerMissed :: forall a. Logger a -> IORef Natural
_loggerPolicy :: forall a. Logger a -> LogPolicy
_loggerScope :: forall a. Logger a -> LogScope
_loggerThreshold :: forall a. Logger a -> LogLevel
_loggerWorker :: forall a. Logger a -> Async ()
_loggerQueue :: forall a. Logger a -> LoggerQueue a
..} LogLevel
level a
msg = do
case LogLevel
_loggerThreshold of
LogLevel
Quiet → () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
LogLevel
threshold
| LogLevel
level LogLevel -> LogLevel -> Bool
forall a. Ord a => a -> a -> Bool
≤ LogLevel
threshold → IO () -> IO ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
TimeSpec
t ← Clock -> IO TimeSpec
getTime Clock
Realtime
LogMessage a -> IO ()
writeWithLogPolicy (LogMessage a -> IO ()) -> LogMessage a -> IO ()
forall a b. NFData a => (a -> b) -> a -> b
$!! LogMessage :: forall a. a -> LogLevel -> LogScope -> TimeSpec -> LogMessage a
LogMessage
{ _logMsg :: a
_logMsg = a
msg
, _logMsgLevel :: LogLevel
_logMsgLevel = LogLevel
level
, _logMsgScope :: LogScope
_logMsgScope = LogScope
_loggerScope
, _logMsgTime :: TimeSpec
_logMsgTime = TimeSpec
t
}
| Bool
otherwise → () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
where
writeWithLogPolicy :: LogMessage a -> IO ()
writeWithLogPolicy !LogMessage a
lmsg
| LogPolicy
_loggerPolicy LogPolicy -> LogPolicy -> Bool
forall α. Eq α => α -> α -> Bool
≡ LogPolicy
LogPolicyBlock = IO Bool -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO Bool -> IO ()) -> IO Bool -> IO ()
forall a b. (a -> b) -> a -> b
$ LoggerQueue a -> LogMessage a -> IO Bool
forall q a. BoundedCloseableQueue q a => q -> a -> IO Bool
writeQueue LoggerQueue a
_loggerQueue LogMessage a
lmsg
| Bool
otherwise = LoggerQueue a -> LogMessage a -> IO (Maybe Bool)
forall q a. BoundedCloseableQueue q a => q -> a -> IO (Maybe Bool)
tryWriteQueue LoggerQueue a
_loggerQueue LogMessage a
lmsg IO (Maybe Bool) -> (Maybe Bool -> IO ()) -> IO ()
forall (m :: * -> *) α β. Monad m => m α -> (α -> m β) -> m β
≫= \case
Just Bool
True → () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Just Bool
False → () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Maybe Bool
Nothing
| LogPolicy
_loggerPolicy LogPolicy -> LogPolicy -> Bool
forall α. Eq α => α -> α -> Bool
≡ LogPolicy
LogPolicyDiscard → IORef Natural -> (Natural -> (Natural, ())) -> IO ()
forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef' IORef Natural
_loggerMissed (\Natural
x → (Natural
x Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
+ Natural
1, ()))
| LogPolicy
_loggerPolicy LogPolicy -> LogPolicy -> Bool
forall α. Eq α => α -> α -> Bool
≡ LogPolicy
LogPolicyRaise → LoggerException a -> IO ()
forall (m :: * -> *) e a. (MonadBase IO m, Exception e) => e -> m a
throwIO (LoggerException a -> IO ()) -> LoggerException a -> IO ()
forall a b. (a -> b) -> a -> b
$ LogMessage a -> LoggerException a
forall a. LogMessage a -> LoggerException a
QueueFullException LogMessage a
lmsg
| Bool
otherwise → () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
{-# INLINEABLE loggCtx #-}
instance LoggerCtx (Logger a) a where
loggerFunIO :: Logger a -> LogFunctionIO a
loggerFunIO = Logger a -> LogFunctionIO a
forall a.
(Show a, Typeable a, NFData a) =>
Logger a -> LogFunctionIO a
loggCtx
setLoggerLevel :: (LogLevel -> f LogLevel) -> Logger a -> f (Logger a)
setLoggerLevel = (LogLevel -> f LogLevel) -> Logger a -> f (Logger a)
forall a. Lens' (Logger a) LogLevel
loggerThreshold
setLoggerScope :: (LogScope -> f LogScope) -> Logger a -> f (Logger a)
setLoggerScope = (LogScope -> f LogScope) -> Logger a -> f (Logger a)
forall a. Lens' (Logger a) LogScope
loggerScope
setLoggerPolicy :: (LogPolicy -> f LogPolicy) -> Logger a -> f (Logger a)
setLoggerPolicy = (LogPolicy -> f LogPolicy) -> Logger a -> f (Logger a)
forall a. Lens' (Logger a) LogPolicy
loggerPolicy
type LoggerT a = LoggerCtxT (Logger a)
runLoggerT ∷ LoggerT a m α → Logger a → m α
runLoggerT :: LoggerT a m α -> Logger a -> m α
runLoggerT = LoggerT a m α -> Logger a -> m α
forall ctx (m :: * -> *) α. LoggerCtxT ctx m α -> ctx -> m α
runLoggerCtxT
{-# INLINE runLoggerT #-}
runLogT
∷ (MonadBaseControl IO m, MonadIO m)
⇒ LoggerConfig
→ LoggerBackend msg
→ LoggerT msg m α
→ m α
runLogT :: LoggerConfig -> LoggerBackend msg -> LoggerT msg m α -> m α
runLogT LoggerConfig
config LoggerBackend msg
backend = LoggerConfig -> LoggerBackend msg -> (Logger msg -> m α) -> m α
forall (μ :: * -> *) a α.
(MonadIO μ, MonadBaseControl IO μ) =>
LoggerConfig -> LoggerBackend a -> (Logger a -> μ α) -> μ α
withLogger LoggerConfig
config LoggerBackend msg
backend ((Logger msg -> m α) -> m α)
-> (LoggerT msg m α -> Logger msg -> m α) -> LoggerT msg m α -> m α
forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ LoggerT msg m α -> Logger msg -> m α
forall a (m :: * -> *) α. LoggerT a m α -> Logger a -> m α
runLoggerT