module Colog.Json.Action
( logToHandle
, encodeMessage
) where
import Colog.Core
import Colog.Json.Internal.Structured
import Control.Exception
import Data.Aeson.Encoding as Aeson
import qualified Data.Aeson.Key as Aeson.Key
import qualified Data.ByteString.Builder as Builder
import Data.Coerce
import Data.Foldable
import qualified Data.List.NonEmpty as NE
import qualified Data.Text.Lazy as TL
import qualified Data.Text.Lazy.Builder as TLB
import System.IO
logToHandle :: Handle -> LogAction IO Message
logToHandle :: Handle -> LogAction IO Message
logToHandle Handle
h = forall (m :: * -> *) msg. (msg -> m ()) -> LogAction m msg
LogAction \Message
m ->
let msg :: Encoding
msg = Message -> Encoding
encodeMessage Message
m
in forall e a. Exception e => IO a -> IO (Either e a)
try (Handle -> Builder -> IO ()
Builder.hPutBuilder Handle
h forall a b. (a -> b) -> a -> b
$ forall tag. Encoding' tag -> Builder
Aeson.fromEncoding Encoding
msg forall a. Semigroup a => a -> a -> a
<> Char -> Builder
Builder.char7 Char
'\n') forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Left SomeException
e -> do
Handle -> Builder -> IO ()
Builder.hPutBuilder Handle
h forall a b. (a -> b) -> a -> b
$ forall tag. Encoding' tag -> Builder
Aeson.fromEncoding (Series -> Encoding
Aeson.pairs
forall a b. (a -> b) -> a -> b
$ forall a. Monoid a => [a] -> a
mconcat
[ Key -> Encoding -> Series
Aeson.pair Key
"namespace" (forall a. Text -> Encoding' a
Aeson.text Text
"logger")
, Key -> Encoding -> Series
Aeson.pair Key
"exception" (forall a. String -> Encoding' a
Aeson.string (forall a. Show a => a -> String
show (SomeException
e::SomeException)))
])
forall a. Semigroup a => a -> a -> a
<> Char -> Builder
Builder.char7 Char
'\n'
Right ()
_ -> forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
encodeMessage :: Message -> Encoding
{-# INLINE encodeMessage #-}
encodeMessage :: Message -> Encoding
encodeMessage Message{Int
Seq Structured
Severity
LogStr
message :: Message -> LogStr
attributes :: Message -> Seq Structured
thread_id :: Message -> Int
message_severity :: Message -> Severity
message :: LogStr
attributes :: Seq Structured
thread_id :: Int
message_severity :: Severity
..} = Series -> Encoding
Aeson.pairs forall a b. (a -> b) -> a -> b
$ forall a. Monoid a => [a] -> a
mconcat [Series]
fields where
fields :: [Series]
fields =
[ case Maybe Text
namespace of
Maybe Text
Nothing -> forall a. Monoid a => a
mempty
Just Text
xs -> Key -> Encoding -> Series
Aeson.pair Key
"namespace" forall a b. (a -> b) -> a -> b
$ forall a. Text -> Encoding' a
Aeson.lazyText Text
xs
, Key -> Encoding -> Series
Aeson.pair Key
"severity" forall a b. (a -> b) -> a -> b
$ Severity -> Encoding
encodeSeverity Severity
message_severity
, Key -> Encoding -> Series
Aeson.pair Key
"thread" forall a b. (a -> b) -> a -> b
$ Int -> Encoding
Aeson.int Int
thread_id
, case Maybe Series
user_data of
Maybe Series
Nothing -> forall a. Monoid a => a
mempty
Just Series
xs -> Key -> Encoding -> Series
Aeson.pair Key
"data" forall a b. (a -> b) -> a -> b
$ Series -> Encoding
Aeson.pairs Series
xs
, Key -> Encoding -> Series
Aeson.pair Key
"message" forall a b. (a -> b) -> a -> b
$ forall a. Text -> Encoding' a
lazyText forall a b. (a -> b) -> a -> b
$ coerce :: forall a b. Coercible a b => a -> b
coerce Builder -> Text
TLB.toLazyText LogStr
message
]
namespace :: Maybe Text
namespace = Text -> [Text] -> Text
TL.intercalate Text
"."forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a. Foldable t => t a -> [a]
toList forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. [a] -> Maybe (NonEmpty a)
NE.nonEmpty
[ Text -> Text
TL.fromStrict Text
tm
| Segment Text
tm <- forall (t :: * -> *) a. Foldable t => t a -> [a]
toList Seq Structured
attributes
]
user_data :: Maybe Series
user_data = forall (t :: * -> *) m. (Foldable t, Monoid m) => t m -> m
fold forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. [a] -> Maybe (NonEmpty a)
NE.nonEmpty
[ Key -> Encoding -> Series
pair (Text -> Key
Aeson.Key.fromText Text
key) Encoding
attributeValue
| Attr Text
key Encoding
attributeValue <- forall (t :: * -> *) a. Foldable t => t a -> [a]
toList Seq Structured
attributes
]