@@ -26,17 +26,22 @@ import qualified Control.Tracer as T
2626import Data.Aeson ((.=) )
2727import qualified Data.Aeson as AE
2828import qualified Data.Aeson.Encoding as AE
29+ import qualified Data.Aeson.KeyMap as AE
2930import Data.Functor.Contravariant
3031import Data.Maybe (fromMaybe )
3132import Data.Text as T (Text , intercalate , null , pack )
3233import Data.Text.Lazy (toStrict )
3334import Data.Text.Lazy.Builder as TB
3435import Data.Text.Lazy.Encoding (decodeUtf8 )
35- import Data.Time (UTCTime , defaultTimeLocale , formatTime , getCurrentTime )
36+ import Data.Time (UTCTime , addUTCTime , defaultTimeLocale , formatTime , getCurrentTime )
37+ import GHC.Clock (getMonotonicTime )
3638import Network.HostName
3739import System.IO.Unsafe (unsafePerformIO )
3840
3941
42+ data I a = I a
43+ instance Functor I where fmap f (I x) = I (f x)
44+
4045encodingToText :: AE. Encoding -> Text
4146{-# INLINE encodingToText #-}
4247encodingToText = toStrict . decodeUtf8 . AE. encodingToLazyByteString
@@ -45,6 +50,10 @@ timeFormatted :: UTCTime -> Text
4550{-# INLINE timeFormatted #-}
4651timeFormatted = pack . formatTime defaultTimeLocale " %F %H:%M:%S%4QZ"
4752
53+ timeFormattedT :: UTCTime -> Text
54+ {-# INLINE timeFormattedT #-}
55+ timeFormattedT = pack . formatTime defaultTimeLocale " %FT%H:%M:%S%8QZ"
56+
4857-- If the hostname in the logs should be anything different from the system reported hostname,
4958-- a new field would need to be added to PreFormatted to carry a new hostname argument to preFormatted.
5059hostname :: Text
@@ -84,13 +93,21 @@ preFormatted withForHuman =
8493 flip contramapM
8594 (\ case
8695 (lc, Right msg) -> do
96+ tm <- liftIO getMonotonicTime
8797 time <- liftIO getCurrentTime
98+ let tmf tm' = flip addUTCTime time $ fromRational $ tm' - toRational tm
8899 threadId <- liftIO myThreadId
89100 let ns' = lcNSPrefix lc ++ lcNSInner lc
90101 threadTextShortened = T. pack $ drop 9 $ show threadId -- drop "ThreadId " prefix
91102 details = fromMaybe DNormal (lcDetails lc)
92103 condForHuman = let txt = forHuman msg in if T. null txt then Nothing else Just txt
93- machineFormatted = AE. toEncoding $ forMachine details msg
104+ obj = forMachine details msg
105+ -- nasty special case for a numeric "mux_tm" field
106+ I obj' = (\ f -> AE. alterF f " mux_at" obj) $ \ case
107+ Nothing -> I Nothing
108+ Just (AE. Number tm') -> I $ Just $ AE. String $ timeFormattedT $ tmf $ toRational tm'
109+ Just x -> I $ Just x
110+ machineFormatted = AE. toEncoding $ obj'
94111
95112 pure (lc, Right (PreFormatted
96113 { pfForHuman = if withForHuman then condForHuman else Nothing
0 commit comments