{- | Generate JSON logs compatible with LogZ.io. `logMsgJs` and `formatMsgJs` are both re-exported, so it should not be necessary to import this module directly.

TODO: Rename this to LogZ since it generates fields specific to that service.
-}
{-# LANGUAGE OverloadedStrings  #-}
module LuminescentDreams.Logger.JSON ( logMsgJs, formatMsgJs ) where

import           Data.Monoid
import qualified Data.Aeson               as Aeson
import qualified Data.Map                 as M
import           Data.String
import qualified Data.Text.Format         as TF
import qualified Data.Text.Lazy.Encoding  as TEnc
import qualified Data.Time                as Time
import qualified Data.Text.Lazy           as T

import           LuminescentDreams.Logger.Internal

{- | Log a message in LogZ format. This uses `formatMsgJs` to generate the actual format string. -}
logMsgJs :: Logger -> LogLevel -> [(String, Aeson.Value)] -> IO ()
logMsgJs (Logger writer pri) lvl msg =
  if lvl >= pri
    then do
      t <- Time.getCurrentTime
      writer $ formatMsgJs t lvl msg
    else return ()

{- | Format a message for LogZ JSON format. -}
formatMsgJs :: Time.UTCTime -> LogLevel -> [(String, Aeson.Value)] -> T.Text
formatMsgJs time level msg =
  let msg_ = msg <> [ ("@timestamp", fromString $ Time.formatTime Time.defaultTimeLocale "%Y-%m-%dT%H:%M:%S" time)
                    , ("@level", Aeson.String $ T.toStrict $ TF.format "{}" (TF.Only level))
                    ]
  in TEnc.decodeUtf8 $ Aeson.encode $ M.fromList msg_