log 0.2.0 → 0.2.1
raw patch · 4 files changed
+58/−47 lines, 4 files
Files
- log.cabal +1/−1
- src/Log/Backend/PostgreSQL.hs +1/−7
- src/Log/Backend/StandardOutput.hs +2/−34
- src/Log/Data.hs +54/−5
log.cabal view
@@ -1,5 +1,5 @@ name: log-version: 0.2.0+version: 0.2.1 synopsis: Structured logging solution with multiple backends description: A library that provides a way to record structured log messages with multiple backends.
src/Log/Backend/PostgreSQL.hs view
@@ -4,7 +4,6 @@ import Control.Concurrent import Control.Exception import Data.Aeson-import Data.ByteString (ByteString) import Data.ByteString.Lazy (toStrict) import Data.Monoid import Data.Monoid.Utils@@ -33,18 +32,13 @@ , "now()" , "," <?> n , "," <?> lmTime- , "," <?> sqlifyLevel lmLevel+ , "," <?> showLogLevel lmLevel , "," <?> lmComponent , "," <?> Array1 lmDomain , "," <?> lmMessage , "," <?> toStrict (encode lmData) <> "::jsonb" , ")" ]-- sqlifyLevel :: LogLevel -> ByteString- sqlifyLevel LogAttention = "attention"- sqlifyLevel LogInfo = "info"- sqlifyLevel LogTrace = "trace" ts :: TransactionSettings ts = def {
src/Log/Backend/StandardOutput.hs view
@@ -1,15 +1,6 @@-{-# LANGUAGE CPP, OverloadedStrings, RecordWildCards #-}+{-# LANGUAGE OverloadedStrings #-} module Log.Backend.StandardOutput (stdoutLogger) where -import Data.Aeson.Encode.Pretty-import Data.Aeson.Types-import Data.ByteString.Lazy (toStrict)-import Data.Time-#if !MIN_VERSION_time(1,5,0)-import System.Locale-#endif-import qualified Data.Text as T-import qualified Data.Text.Encoding as T import qualified Data.Text.IO as T import Log.Data@@ -17,27 +8,4 @@ -- | Create logger that prints messages to standard output. stdoutLogger :: IO Logger-stdoutLogger = mkLogger "stdout" printLogMessage--printLogMessage :: LogMessage -> IO ()-printLogMessage LogMessage{..} = T.putStrLn . T.concat $ [- T.pack $ formatTime defaultTimeLocale "%Y-%m-%d %H:%M:%S" lmTime- , " "- , textifyLevel lmLevel- , " "- , T.intercalate "/" $ lmComponent : lmDomain- , ": "- , lmMessage- ] ++ if lmData == emptyObject- then []- else [" ", textifyData lmData]- where- textifyData :: Value -> T.Text- textifyData = T.decodeUtf8 . toStrict . encodePretty' defConfig {- confIndent = 2- }-- textifyLevel :: LogLevel -> T.Text- textifyLevel LogAttention = "ATTENTION"- textifyLevel LogInfo = "INFO"- textifyLevel LogTrace = "TRACE"+stdoutLogger = mkLogger "stdout" $ T.putStrLn . showLogMessage
src/Log/Data.hs view
@@ -1,36 +1,85 @@-{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE CPP, OverloadedStrings, RecordWildCards #-} module Log.Data ( LogLevel(..)+ , showLogLevel+ , readLogLevel , LogMessage(..)+ , showLogMessage ) where import Control.DeepSeq import Data.Aeson-import Data.Text (Text)+import Data.Aeson.Encode.Pretty+import Data.Aeson.Types+import Data.ByteString.Lazy (toStrict) import Data.Time+#if !MIN_VERSION_time(1,5,0)+import System.Locale+#endif+import qualified Data.Text as T+import qualified Data.Text.Encoding as T -- | Available log levels. data LogLevel = LogAttention | LogInfo | LogTrace deriving (Bounded, Eq, Ord, Show) +readLogLevel :: T.Text -> LogLevel+readLogLevel "attention" = LogAttention+readLogLevel "info" = LogInfo+readLogLevel "trace" = LogTrace+readLogLevel level = error $ "readLogLevel: unknown level: " ++ T.unpack level++showLogLevel :: LogLevel -> T.Text+showLogLevel LogAttention = "attention"+showLogLevel LogInfo = "info"+showLogLevel LogTrace = "trace"+ instance NFData LogLevel where rnf = (`seq` ()) -- | Represents message to be logged. data LogMessage = LogMessage { -- | Component of an application.- lmComponent :: !Text+ lmComponent :: !T.Text -- | Aplication log domain.-, lmDomain :: ![Text]+, lmDomain :: ![T.Text] -- | Time of log. , lmTime :: !UTCTime -- | Log level. , lmLevel :: !LogLevel -- | Message to be logged.-, lmMessage :: !Text+, lmMessage :: !T.Text -- | Additional data associated with the message. , lmData :: !Value } deriving (Eq, Show)++showLogMessage :: LogMessage -> T.Text+showLogMessage LogMessage{..} = T.concat $ [+ T.pack $ formatTime defaultTimeLocale "%Y-%m-%d %H:%M:%S" lmTime+ , " "+ , T.toUpper $ showLogLevel lmLevel+ , " "+ , T.intercalate "/" $ lmComponent : lmDomain+ , ": "+ , lmMessage+ ] ++ if lmData == emptyObject+ then []+ else [" ", textifyData lmData]+ where+ textifyData :: Value -> T.Text+ textifyData = T.decodeUtf8 . toStrict . encodePretty' defConfig {+ confIndent = 2+ }++instance ToJSON LogMessage where+ toJSON LogMessage{..} = object [+ "component" .= lmComponent+ , "domain" .= lmDomain+ , "time" .= lmComponent+ , "level" .= showLogLevel lmLevel+ , "message" .= lmMessage+ , "data" .= lmData+ ] instance NFData LogMessage where rnf LogMessage{..} = rnf lmComponent