packages feed

lumberjack 0.1.0.0 → 0.1.0.1

raw patch · 4 files changed

+159/−84 lines, 4 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

Files

CHANGELOG.md view
@@ -1,5 +1,9 @@ # Revision history for lumberjack +## 0.1.0.1 -- 2020-02-14++* Updates to documentation and internal code formatting.  No functionality updates.+ ## 0.1.0.0 -- 2020-02-13  * Initial Lumberjack logger implementation, based on internal usage.
example/ExampleLog.hs view
@@ -27,6 +27,10 @@  exampleTextLoggingInIO :: IO () exampleTextLoggingInIO = do++  -- This function represents the main code that logging output should+  -- be generated from.  Here's an example of generating a log message:+   writeLogM $ T.pack "This is a logged text message in base IO"    -- In situations where the current monad doesn't provide the log@@ -48,7 +52,6 @@ exampleStringLoggingInIO :: IO () exampleStringLoggingInIO = do   writeLogM ("This is a logged string message in base IO" :: String)-  -- example of adjust   ----------------------------------------------------------------------@@ -102,23 +105,46 @@  exampleStringLoggingInMyMonad2 :: MyMonad2 () exampleStringLoggingInMyMonad2 = do++  -- As noted above, this function represents the main body of code.+  -- The logging messages would be interspersed in this code at+  -- appropriate locations to generate the various logged information.+   writeLogM $ msgWith { logText = "This is a logged string message in MyMonad" }+   -- withLogTag is a helper to set the logTags field for subsequently logged messages   withLogTag "loc" "inner" $ do     writeLogM $ msgWith { logText = "doing stuff..." }     withLogTag "style" "(deep)" $ do++      -- Tags accumulate and are applied to all messages logged.       writeLogM $ msgWith { logText = "deep thinking",                             logLevel = Info                           }+       -- There's also a HasLog for simple messages in this monad       writeLogM $ ("Text messages can be logged as well" :: T.Text)++    -- Calls to other functions can be logged on entry and exit by+    -- simply using this wrapper.  Note also that this is outside of+    -- the inner withLogTag context, so only the outer tags are+    -- applied, but the context for those tags extends to the logging+    -- from the functions being called.     logFunctionCallM "invoking subFunction" $ subFunction++  -- Helpers can be used to log various types of information.  Here is+  -- an indication of progress being made by the code.   logProgressM "making good progress"+   writeLogM $ msgWith { logText = "Done now", logLevel = Warning } + subFunction :: (WithLog LogMessage m, Monad m) => m () subFunction =+  -- An example of a monadic function called that can perform logging+  -- with minimal constraints on the current Monad type.   writeLogM $ msgWith { logText = "subFunction executing" }+  ---------------------------------------------------------------------- 
lumberjack.cabal view
@@ -1,6 +1,6 @@ cabal-version:       >=1.10 name:                lumberjack-version:             0.1.0.0+version:             0.1.0.1 synopsis:            Trek through your code forest and make logs description:         This is a logging facility.  Yes, there are many, and this is the one                      with a beard, wearing flannel and boots, that gets the job done.  It's@@ -12,7 +12,7 @@                        performed in a monad stack with a MonadIO context to allow                        writing to files.                      . -                     * The specific logging action implementaions are managed separately+                     * The specific logging action implementations are managed separately                        from the actions of logging messages in the target code.  This                        allows logging to be configurable and the manner of logging to                        be specified at startup time without requiring changes in the
src/Lumberjack.hs view
@@ -19,10 +19,36 @@ -- Maintainer  : kquick@galois.com -- Stability   : experimental -- Portability : POSIX--- | -- -- This module defines a general logging facility that can be used to -- output log messages to various targets.+--+-- The 'LogAction' is the fundamental operation that decides how to+-- log a provided message.+--+-- Code wishing to output a logged message simply uses the LogAction+-- object:+--+-- > writeLog action msg+--+-- For convenience, the LogAction can be stored in the local operating+-- monad context, from which it can be retrieved (and modified).  A+-- monad which can supply a LogAction is a member of the HasLog class,+-- and the 'writeLogM' function will automatically retrieve the+-- LogAction from the monad and write to it:+--+-- > writeLogM msg+--+-- LogActions can be combined via Semigroup operations (<>) and the+-- resulting LogAction will perform both actions with each message.+-- The Monoidal mempty LogAction simply does nothing.  For example,+-- logging to both a file and stdout can be done by @logToFile <>+-- logToStdout@.+--+-- LogActions are also Contravariant (and Divisible and Decidable) to+-- allow easy conversion of a LogAction for the base message type into+-- a LogAction for a different message type (or types) that can be+-- converted to (and combined into) the base message type. -------------------------------------------  module Lumberjack@@ -32,9 +58,13 @@   , LoggingMonad(..)   , writeLogM     -- * Logging Utilities+    --+    -- The following utility functions can be used to adjust or wrap+    -- LogActions to provide additional functionality.   , safeLogAction   , logFilter-    -- * Default LogMessage+    -- * LogMessage rich logging type+    -- $richMsgType   , Severity(..)   , LogType(..)   , LogMessage(..)@@ -42,10 +72,12 @@   , WithLog   , withLogTag   , addLogActionTime-    -- * Output formatting for LogMessage+    -- ** Output formatting for LogMessage+    -- $richMsgFormatting   , cvtLogMessageToPlainText   , cvtLogMessageToANSITermText     -- * Helpers and convenience functions+    -- $helpers   , logFunctionCall, logFunctionCallM   , logProgress, logProgressM   , tshow@@ -75,34 +107,8 @@   -- ----------------------------------------------------------------------+ -- * Interface for Logging------ The 'LogAction' is the fundamental operation that decides how to--- log a provided message.------ Code wishing to output a logged message simply uses the LogAction--- object:------ > writeLog action msg------ For convenience, the LogAction can be stored in the local operating--- monad context, from which it can be retrieved (and modified).  A--- monad which can supply a LogAction is a member of the HasLog class,--- and the 'writeLogM' function will automatically retrieve the--- LogAction from the monad and write to it:------ > writeLogM msg------ LogActions can be combined via Semigroup operations (<>) and the--- resulting LogAction will perform both actions with each message.--- The Monoidal mempty LogAction simply does nothing.  For example,--- logging to both a file and stdout can be done by @logToFile <>--- logToStdout@.------ LogActions are also Contravariant (and Divisible and Decidable) to--- allow easy conversion of a LogAction for the base message type into--- a LogAction for a different message type (or types) that can be--- converted to (and combined into) the base message type.  -- | The LogAction holds the ability to log a message of type 'msg' -- (the second parameter) via a monad 'm' (the first parameter).@@ -135,33 +141,46 @@   lose f = LogAction $ \a -> absurd (f a)   choose split l r = LogAction $ either (writeLog l) (writeLog r) . split --- | Any monad which will support retrieving or adjusting a LogAction--- must support the 'HasLog' class.++-- | Any monad which will support retrieving a LogAction from the+-- Monad's environment should support the 'HasLog' class. class Monad m => HasLog msg m where   getLogAction :: m (LogAction m msg) ++-- | This type is a Constraint that should be applied to any client+-- function that will perform logging in a monad context.  The 'msg'+-- is the type of message that will be logged, and the 'm' is the+-- monad under which the logging is performed.+type WithLog msg m = ({- X.MonadCatch m, -} HasLog msg m)+++-- | An instance of the 'LoggingMonad' class can be defined for the+-- base monadic logging action to allow adjusting that logging action.+-- This class can only be instantiated (and only needs to be+-- instantiated) for the base message type; all other message types+-- will use contramapping to convert their message type to the+-- 'LoggingMonad' base message type. class (Monad m, HasLog msg m) => LoggingMonad msg m where   adjustLogAction :: (forall k. LogAction k msg -> LogAction k msg) -> m a -> m a  --- | This invokes the LogAction's logging handler in a monadic context--- where the logging handler can be retrieved via the 'HasLog' class's--- 'getLogAction' function.+-- | This obtains the 'LogAction' from the current monad's environment+-- to use for outputting the log message.  Most code will use this function. writeLogM :: HasLog msg m => msg -> m () writeLogM m = getLogAction >>= flip writeLog m   ------------------------------------------------------------------------- * LogAction Utilities------ The following utility functions can be used to adjust or wrap--- LogActions to provide additional functionality.+-- * Logging Utilities + -- | Ensures that the LogAction does not fail if the logging operation -- itself throws an exception (the exception is ignored). safeLogAction :: X.MonadCatch m => LogAction m msg -> LogAction m msg safeLogAction a = LogAction $ \m -> X.catch (writeLog a m) (\(_ex :: X.SomeException) -> return ()) + -- | The logFilter can be used on a LogAction to determine which -- messages the LogAction should be invoked for (only those for which -- the filter function returns True).@@ -171,21 +190,29 @@   ------------------------------------------------------------------------- * Default LogMessage+-- * LogMessage rich logging type++-- $richMsgType ----- This is the default 'msg' type for the LogAction, containing the--- various information associated with the logging to be performed.+-- This is an enhanced 'msg' type for the LogAction, containing+-- various auxiliary information associated with the log message.+-- While 'Lumberjack' can be used with other message types, this+-- message type should provide support for most of the common logging+-- auxiliary data and can therefore be used "out of the box". + -- | The Severity indicates the relative importance of the logging -- message.  This can be useful for filtering log messages. data Severity = Debug | Info | Warning | Error deriving (Ord, Eq, Show) + -- | The LogType indicates what type of message this is.  These are -- printed on the log line and can be used for filtering different -- types of log messages. data LogType = Progress | FuncEntry | FuncExit | MiscLog | UserOp   deriving (Eq, Show) + -- | Each logged output is described by a LogMessage object. data LogMessage = LogMessage { logType :: LogType                              , logLevel :: Severity@@ -209,6 +236,7 @@   mempty = LogMessage MiscLog Debug (UTCTime (toEnum 0) (toEnum 0)) [] empty   mappend = (<>) + -- | Helper routine to return an empty LogMessage, whose fields can -- then be updated. msgWith :: LogMessage@@ -221,13 +249,6 @@                                           writeLog a $ m <> mempty { logTime = t }  --- | This type is a Constraint that should be applied to any client--- function that will perform logging in a monad context.  The 'msg'--- is the type of message that will be logged, and the 'm' is the--- monad under which the logging is performed.-type WithLog msg m = ({- X.MonadCatch m, -} HasLog msg m)-- -- | Log messages can have any number of key/value tags applied to -- them.  This function establishes a new key/value tag pair that will -- be in effect for the monadic operation passed as the third@@ -241,17 +262,31 @@  -- ---------------------------------------------------------------------- -- * Output formatting for LogMessage++-- $richMsgFormatting ----- Optimal LogMessage formatting uses prettyprinter output with a+-- When the 'LogMessage' logging type is used, 'Lumberjack' provides a+-- standard set of output formatting functions.  The output uses the+-- prettyprinter package to generate 'Doc' output with annotations+-- specifying the type of markup to be applied to various portions of+-- the output.+--+-- There are multiple rendering functions that can be supplied as+-- contramap converters to the base 'LogAction'.  One rendering+-- function outputs a log message in plain text, while the other uses+-- the prettyprinter-ansi-terminal package to generate various ANSI+-- highlighting and color codes for writing enhanced output to a TTY.+++-- | Normal LogMessage formatting uses prettyprinter output with a -- 'PrettyLogAnn' annotation type which assigns different annotations -- to different parts of the log message.  This is achieved by calling -- 'prettyLogMessage'. ----- Alternatively, the 'Pretty' class 'pretty'--- method can be used to get log message formatting for generic--- annotation types, but the different parts of the message will not--- be distinguished via annotation values.-+-- Alternatively, the 'Pretty' class 'pretty' method can be used to+-- get log message formatting for generic annotation types, but the+-- different parts of the message will not be distinguished via+-- annotation values. data PrettyLogAnn = AnnLogType LogType                   | AnnSeverity Severity                   | AnnTime@@ -317,6 +352,7 @@                                             ]   in foldl (\acc tagval -> acc PP.<+> (ppTag tagval)) mempty + -- | Format the log message with annotation values designating the -- different portions of the pretty-printed value. --@@ -359,18 +395,20 @@ termStyle AnnTagVal = PP_Term.color PP_Term.Black <> PP_Term.bold  --- | Standard function to convert a LogMessage into Text with ANSI--- terminal colors and bolding and other styling.  This can be used as--- the default converter for a logger (via contramap).+-- | Standard 'LogMessage' rendering function to convert a+-- 'LogMessage' into 'Text' with ANSI terminal colors and bolding and+-- other styling.  This can be used as the default converter for a+-- logger (via contramap). cvtLogMessageToANSITermText :: LogMessage -> Text cvtLogMessageToANSITermText = PP_Term.renderStrict .                               PP.reAnnotateS termStyle .                               PP.layoutSmart PP.defaultLayoutOptions .                               prettyLogMessage --- | Standard function for converting a LogMessage into plain Text (no--- colors or bolding, just text).  This can be used as the default--- converter for a logger (via contramap).+-- | Standard 'LogMessage' rendering function for converting a+-- 'LogMessage' into plain 'Text' (no colors or other highlighting).+-- This can be used as the default converter for a logger (via+-- contramap). cvtLogMessageToPlainText :: LogMessage -> Text cvtLogMessageToPlainText = PP_Text.renderStrict .                            PP.layoutSmart PP.defaultLayoutOptions .@@ -378,29 +416,35 @@  -- ---------------------------------------------------------------------- -- * Helpers and convenience functions---++-- $helpers -- These functions are not part of the core Logging implementation, -- but can be useful to clients to perform common or default -- operations. --- | A wrapper for a monadic function call that will log on entry--- (Debug) and exit (Info) from the function, and note the total--- amount of time taken during execution of the function.  Note that--- no strictness is applied to the internal monadic operation, so the--- time taken may be misleading.  Like 'logFunctionCallM' but needs an--- explicit 'LogAction' whereas 'logFunctionCallM' will retrieve the--- 'LogAction' from the current monadic context.++-- | A wrapper for a function call that will call the provided+-- 'LogAction' with a 'Debug' log on entry to the function and an+-- 'Info' log on exit from the function.  The total amount of time+-- taken during execution of the function will be included in the exit+-- log message.  No strictness is applied to the invoked monadic+-- operation, so the time taken may be misleading.  Like+-- 'logFunctionCallM' but needs an explicit 'LogAction' whereas+-- 'logFunctionCallM' will retrieve the 'LogAction' from the current+-- monadic context. logFunctionCall :: (MonadIO m) => LogAction m LogMessage -> Text -> m a -> m a logFunctionCall = logFunctionCallWith . writeLog --- | A wrapper for a monadic function call that will log on entry--- (Debug) and exit (Info) from the function, and note the total--- amount of time taken during execution of the function.  Note that--- no strictness is applied to the internal monadic operation, so the--- time taken may be misleading.++-- | A wrapper for a monadic function call that will 'Debug' log on+-- entry to and 'Info' log on exit from the function.  The exit log+-- will also note the total amount of time taken during execution of+-- the function.  Be advised that no strictness is applied to the+-- internal monadic operation, so the time taken may be misleading. logFunctionCallM :: (MonadIO m, WithLog LogMessage m) => Text -> m a -> m a logFunctionCallM = logFunctionCallWith writeLogM + -- | Internal function implementing the body for 'logFunctionCall' or -- 'logFunctionCallM' logFunctionCallWith :: (MonadIO m) => (LogMessage -> m ()) -> Text -> m a -> m a@@ -415,20 +459,21 @@      return r  --- | Called to output a log message to indicate that some progress has--- been made.+-- | Called to output a log message to indicate that some progress in+-- the current activity has been made. logProgress :: (MonadIO m) => LogAction m LogMessage -> Text -> m () logProgress action txt = writeLog action $ msgWith { logLevel = Info, logType = Progress, logText = txt }  --- | Called to output a log message within a Logging monad to indicate--- that some progress has been made.+-- | Called to output a log message within a 'HasLog' monad to indicate+-- that some progress in the current activity has been made. logProgressM :: (MonadIO m, WithLog LogMessage m) => Text -> m () logProgressM txt = writeLogM $ msgWith { logLevel = Info, logType = Progress, logText = txt }  --- | This is a helper because the LogMessage normally wants a Text,--- but show delivers a String.+-- | This is a helper function.  The LogMessage normally wants a Text,+-- but show delivers a String, so 'tshow' can be used to get the+-- needed format. tshow :: (Show a) => a -> Text tshow = pack . show @@ -442,6 +487,6 @@ -- --  > instance HasLog Env Text IO where --  >     getLogAction = return defaultGetIOLogAction---  >     ...+-- defaultGetIOLogAction :: MonadIO m => LogAction m T.Text defaultGetIOLogAction = LogAction $ liftIO . TIO.hPutStrLn stderr