{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE StandaloneDeriving #-}
module Log
(
debug,
info,
warn,
error,
withContext,
context,
Secret,
mkSecret,
unSecret,
Context (..),
LogContexts (..),
)
where
import Data.Aeson ((.=))
import qualified Data.Aeson as Aeson
import Data.Aeson.Key (fromText)
import qualified GHC.Stack as Stack
import NriPrelude
import qualified Platform
import qualified Platform.Internal as Internal
import qualified Task
import qualified Text.Show
import qualified Prelude
debug :: (Stack.HasCallStack) => Text -> [Context] -> Task e ()
debug :: forall e. HasCallStack => Text -> [Context] -> Task e ()
debug Text
message [Context]
contexts =
(HasCallStack => Text -> ReportStatus -> [Context] -> Task e ())
-> Text -> ReportStatus -> [Context] -> Task e ()
forall a. HasCallStack => (HasCallStack => a) -> a
Stack.withFrozenCallStack
HasCallStack => Text -> ReportStatus -> [Context] -> Task e ()
Text -> ReportStatus -> [Context] -> Task e ()
forall e.
HasCallStack =>
Text -> ReportStatus -> [Context] -> Task e ()
log
Text
message
ReportStatus
ReportAsSucceeded
(Text -> LogLevel -> Context
forall a. (Show a, ToJSON a) => Text -> a -> Context
Context Text
"level" LogLevel
Debug Context -> [Context] -> [Context]
forall a. a -> [a] -> [a]
: [Context]
contexts)
info :: (Stack.HasCallStack) => Text -> [Context] -> Task e ()
info :: forall e. HasCallStack => Text -> [Context] -> Task e ()
info Text
message [Context]
contexts =
(HasCallStack => Text -> ReportStatus -> [Context] -> Task e ())
-> Text -> ReportStatus -> [Context] -> Task e ()
forall a. HasCallStack => (HasCallStack => a) -> a
Stack.withFrozenCallStack
HasCallStack => Text -> ReportStatus -> [Context] -> Task e ()
Text -> ReportStatus -> [Context] -> Task e ()
forall e.
HasCallStack =>
Text -> ReportStatus -> [Context] -> Task e ()
log
Text
message
ReportStatus
ReportAsSucceeded
(Text -> LogLevel -> Context
forall a. (Show a, ToJSON a) => Text -> a -> Context
Context Text
"level" LogLevel
Info Context -> [Context] -> [Context]
forall a. a -> [a] -> [a]
: [Context]
contexts)
warn :: (Stack.HasCallStack) => Text -> [Context] -> Task e ()
warn :: forall e. HasCallStack => Text -> [Context] -> Task e ()
warn Text
message [Context]
contexts =
(HasCallStack => Text -> ReportStatus -> [Context] -> Task e ())
-> Text -> ReportStatus -> [Context] -> Task e ()
forall a. HasCallStack => (HasCallStack => a) -> a
Stack.withFrozenCallStack
HasCallStack => Text -> ReportStatus -> [Context] -> Task e ()
Text -> ReportStatus -> [Context] -> Task e ()
forall e.
HasCallStack =>
Text -> ReportStatus -> [Context] -> Task e ()
log
Text
message
ReportStatus
ReportAsFailed
(Text -> LogLevel -> Context
forall a. (Show a, ToJSON a) => Text -> a -> Context
Context Text
"level" LogLevel
Warn Context -> [Context] -> [Context]
forall a. a -> [a] -> [a]
: [Context]
contexts)
error :: (Stack.HasCallStack) => Text -> [Context] -> Task e ()
error :: forall e. HasCallStack => Text -> [Context] -> Task e ()
error Text
message [Context]
contexts =
(HasCallStack => Text -> ReportStatus -> [Context] -> Task e ())
-> Text -> ReportStatus -> [Context] -> Task e ()
forall a. HasCallStack => (HasCallStack => a) -> a
Stack.withFrozenCallStack
HasCallStack => Text -> ReportStatus -> [Context] -> Task e ()
Text -> ReportStatus -> [Context] -> Task e ()
forall e.
HasCallStack =>
Text -> ReportStatus -> [Context] -> Task e ()
log
Text
message
ReportStatus
ReportAsFailed
(Text -> LogLevel -> Context
forall a. (Show a, ToJSON a) => Text -> a -> Context
Context Text
"level" LogLevel
Error Context -> [Context] -> [Context]
forall a. a -> [a] -> [a]
: [Context]
contexts)
withContext ::
(Stack.HasCallStack) =>
Text ->
[Context] ->
Task e b ->
Task e b
withContext :: forall e b.
HasCallStack =>
Text -> [Context] -> Task e b -> Task e b
withContext Text
name [Context]
contexts Task e b
task =
(HasCallStack => Text -> Task e b -> Task e b)
-> Text -> Task e b -> Task e b
forall a. HasCallStack => (HasCallStack => a) -> a
Stack.withFrozenCallStack
HasCallStack => Text -> Task e b -> Task e b
Text -> Task e b -> Task e b
forall e a. HasCallStack => Text -> Task e a -> Task e a
Internal.tracingSpan
Text
name
( Task e b -> Task e () -> Task e b
forall e a b. Task e a -> Task e b -> Task e a
Platform.finally
Task e b
task
( do
LogContexts -> Task e ()
forall d e. TracingSpanDetails d => d -> Task e ()
Platform.setTracingSpanDetails ([Context] -> LogContexts
LogContexts [Context]
contexts)
Text -> Task e ()
forall e. Text -> Task e ()
Platform.setTracingSpanSummary Text
name
)
)
context :: (Show a, Aeson.ToJSON a) => Text -> a -> Context
context :: forall a. (Show a, ToJSON a) => Text -> a -> Context
context = Text -> a -> Context
forall a. (Show a, ToJSON a) => Text -> a -> Context
Context
data Context where
Context :: (Show a, Aeson.ToJSON a) => Text -> a -> Context
deriving instance Show Context
newtype LogContexts
= LogContexts [Context]
instance Aeson.ToJSON LogContexts where
toJSON :: LogContexts -> Value
toJSON (LogContexts [Context]
contexts) =
[Context]
contexts
[Context] -> ([Context] -> [Pair]) -> [Pair]
forall a b. a -> (a -> b) -> b
|> (Context -> Pair) -> [Context] -> [Pair]
forall (m :: * -> *) a value.
Functor m =>
(a -> value) -> m a -> m value
map (\(Context Text
key a
val) -> (Text -> Key
fromText Text
key) Key -> a -> Pair
forall v. ToJSON v => Key -> v -> Pair
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= a
val)
[Pair] -> ([Pair] -> Value) -> Value
forall a b. a -> (a -> b) -> b
|> [Pair] -> Value
Aeson.object
toEncoding :: LogContexts -> Encoding
toEncoding (LogContexts [Context]
contexts) =
[Context]
contexts
[Context] -> ([Context] -> Series) -> Series
forall a b. a -> (a -> b) -> b
|> (Context -> Series) -> [Context] -> Series
forall m a. Monoid m => (a -> m) -> [a] -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
Prelude.foldMap (\(Context Text
key a
val) -> (Text -> Key
fromText Text
key) Key -> a -> Series
forall v. ToJSON v => Key -> v -> Series
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= a
val)
Series -> (Series -> Encoding) -> Encoding
forall a b. a -> (a -> b) -> b
|> Series -> Encoding
Aeson.pairs
instance Internal.TracingSpanDetails LogContexts
mkSecret :: a -> Secret a
mkSecret :: forall a. a -> Secret a
mkSecret = a -> Secret a
forall a. a -> Secret a
Secret
unSecret :: Secret a -> a
unSecret :: forall a. Secret a -> a
unSecret (Secret a
x) = a
x
newtype Secret a
= Secret a
deriving (Secret a -> Secret a -> Bool
(Secret a -> Secret a -> Bool)
-> (Secret a -> Secret a -> Bool) -> Eq (Secret a)
forall a. Eq a => Secret a -> Secret a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a. Eq a => Secret a -> Secret a -> Bool
== :: Secret a -> Secret a -> Bool
$c/= :: forall a. Eq a => Secret a -> Secret a -> Bool
/= :: Secret a -> Secret a -> Bool
Prelude.Eq, (forall a b. (a -> b) -> Secret a -> Secret b)
-> (forall a b. a -> Secret b -> Secret a) -> Functor Secret
forall a b. a -> Secret b -> Secret a
forall a b. (a -> b) -> Secret a -> Secret b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall a b. (a -> b) -> Secret a -> Secret b
fmap :: forall a b. (a -> b) -> Secret a -> Secret b
$c<$ :: forall a b. a -> Secret b -> Secret a
<$ :: forall a b. a -> Secret b -> Secret a
Prelude.Functor)
instance Prelude.Applicative Secret where
Secret a -> b
f <*> :: forall a b. Secret (a -> b) -> Secret a -> Secret b
<*> Secret a
x = b -> Secret b
forall a. a -> Secret a
Secret (a -> b
f a
x)
pure :: forall a. a -> Secret a
pure = a -> Secret a
forall a. a -> Secret a
Secret
instance Show (Secret a) where
showsPrec :: Int -> Secret a -> ShowS
showsPrec Int
p Secret a
_ =
Bool -> ShowS -> ShowS
Text.Show.showParen (Int
p Int -> Int -> Bool
forall comparable.
Ord comparable =>
comparable -> comparable -> Bool
> Int
10) (String -> ShowS
Text.Show.showString String
"Secret \"*****\"")
instance Aeson.ToJSON (Secret a) where
toJSON :: Secret a -> Value
toJSON Secret a
_ = Text -> Value
Aeson.String Text
"Secret *****"
data LogLevel
= Debug
| Info
| Warn
| Error
deriving ((forall x. LogLevel -> Rep LogLevel x)
-> (forall x. Rep LogLevel x -> LogLevel) -> Generic LogLevel
forall x. Rep LogLevel x -> LogLevel
forall x. LogLevel -> Rep LogLevel x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. LogLevel -> Rep LogLevel x
from :: forall x. LogLevel -> Rep LogLevel x
$cto :: forall x. Rep LogLevel x -> LogLevel
to :: forall x. Rep LogLevel x -> LogLevel
Generic, Int -> LogLevel -> ShowS
[LogLevel] -> ShowS
LogLevel -> String
(Int -> LogLevel -> ShowS)
-> (LogLevel -> String) -> ([LogLevel] -> ShowS) -> Show LogLevel
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> LogLevel -> ShowS
showsPrec :: Int -> LogLevel -> ShowS
$cshow :: LogLevel -> String
show :: LogLevel -> String
$cshowList :: [LogLevel] -> ShowS
showList :: [LogLevel] -> ShowS
Show)
instance Aeson.ToJSON LogLevel
data ReportStatus = ReportAsFailed | ReportAsSucceeded
log :: (Stack.HasCallStack) => Text -> ReportStatus -> [Context] -> Task e ()
log :: forall e.
HasCallStack =>
Text -> ReportStatus -> [Context] -> Task e ()
log Text
msg ReportStatus
reportStatus [Context]
contexts =
Text -> Task e () -> Task e ()
forall e a. HasCallStack => Text -> Task e a -> Task e a
Internal.tracingSpan Text
msg (Task e () -> Task e ()) -> Task e () -> Task e ()
forall a b. (a -> b) -> a -> b
<| do
LogContexts -> Task e ()
forall d e. TracingSpanDetails d => d -> Task e ()
Platform.setTracingSpanDetails ([Context] -> LogContexts
LogContexts [Context]
contexts)
case ReportStatus
reportStatus of
ReportStatus
ReportAsSucceeded -> () -> Task e ()
forall a x. a -> Task x a
Task.succeed ()
ReportStatus
ReportAsFailed -> Task e ()
forall e. Task e ()
Platform.markTracingSpanFailed