katip-0.5.0.0: A structured logging framework.

Safe HaskellNone
LanguageHaskell2010

Katip.Core

Description

This module is not meant to be imported directly and may contain internal mechanisms that will change without notice.

Synopsis

Documentation

readMay :: Read a => String -> Maybe a #

newtype Namespace #

Represents a heirarchy of namespaces going from general to specific. For instance: ["processname", "subsystem"]. Note that single-segment namespaces can be created using IsString/OverloadedStrings, so "foo" will result in Namespace ["foo"].

Constructors

Namespace 

Fields

Instances

Eq Namespace # 
Ord Namespace # 
Read Namespace # 
Show Namespace # 
IsString Namespace # 
Generic Namespace # 

Associated Types

type Rep Namespace :: * -> * #

Semigroup Namespace # 
Monoid Namespace # 
Lift Namespace # 

Methods

lift :: Namespace -> Q Exp #

ToJSON Namespace # 
FromJSON Namespace # 
type Rep Namespace # 
type Rep Namespace = D1 (MetaData "Namespace" "Katip.Core" "katip-0.5.0.0-5Om1z0bPkZ0A49qyD7iqyp" True) (C1 (MetaCons "Namespace" PrefixI True) (S1 (MetaSel (Just Symbol "unNamespace") NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 [Text])))

intercalateNs :: Namespace -> [Text] #

Ready namespace for emission with dots to join the segments.

newtype Environment #

Application environment, like prod, devel, testing.

Constructors

Environment 

Fields

Instances

Eq Environment # 
Ord Environment # 
Read Environment # 
Show Environment # 
IsString Environment # 
Generic Environment # 

Associated Types

type Rep Environment :: * -> * #

ToJSON Environment # 
FromJSON Environment # 
type Rep Environment # 
type Rep Environment = D1 (MetaData "Environment" "Katip.Core" "katip-0.5.0.0-5Om1z0bPkZ0A49qyD7iqyp" True) (C1 (MetaCons "Environment" PrefixI True) (S1 (MetaSel (Just Symbol "getEnvironment") NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 Text)))

data Severity #

Constructors

DebugS

Debug messages

InfoS

Information

NoticeS

Normal runtime Conditions

WarningS

General Warnings

ErrorS

General Errors

CriticalS

Severe situations

AlertS

Take immediate action

EmergencyS

System is unusable

Instances

Bounded Severity # 
Enum Severity # 
Eq Severity # 
Ord Severity # 
Read Severity # 
Show Severity # 
Generic Severity # 

Associated Types

type Rep Severity :: * -> * #

Methods

from :: Severity -> Rep Severity x #

to :: Rep Severity x -> Severity #

Lift Severity # 

Methods

lift :: Severity -> Q Exp #

ToJSON Severity # 
FromJSON Severity # 
type Rep Severity # 
type Rep Severity = D1 (MetaData "Severity" "Katip.Core" "katip-0.5.0.0-5Om1z0bPkZ0A49qyD7iqyp" False) ((:+:) ((:+:) ((:+:) (C1 (MetaCons "DebugS" PrefixI False) U1) (C1 (MetaCons "InfoS" PrefixI False) U1)) ((:+:) (C1 (MetaCons "NoticeS" PrefixI False) U1) (C1 (MetaCons "WarningS" PrefixI False) U1))) ((:+:) ((:+:) (C1 (MetaCons "ErrorS" PrefixI False) U1) (C1 (MetaCons "CriticalS" PrefixI False) U1)) ((:+:) (C1 (MetaCons "AlertS" PrefixI False) U1) (C1 (MetaCons "EmergencyS" PrefixI False) U1))))

data Verbosity #

Verbosity controls the amount of information (columns) a Scribe emits during logging.

The convention is: - V0 implies no additional payload information is included in message. - V3 implies the maximum amount of payload information. - Anything in between is left to the discretion of the developer.

Constructors

V0 
V1 
V2 
V3 

Instances

Enum Verbosity # 
Eq Verbosity # 
Ord Verbosity # 
Read Verbosity # 
Show Verbosity # 
Generic Verbosity # 

Associated Types

type Rep Verbosity :: * -> * #

Lift Verbosity # 

Methods

lift :: Verbosity -> Q Exp #

type Rep Verbosity # 
type Rep Verbosity = D1 (MetaData "Verbosity" "Katip.Core" "katip-0.5.0.0-5Om1z0bPkZ0A49qyD7iqyp" False) ((:+:) ((:+:) (C1 (MetaCons "V0" PrefixI False) U1) (C1 (MetaCons "V1" PrefixI False) U1)) ((:+:) (C1 (MetaCons "V2" PrefixI False) U1) (C1 (MetaCons "V3" PrefixI False) U1)))

newtype LogStr #

Log message with Builder underneath; use <> to concat in O(1).

Constructors

LogStr 

Fields

Instances

Show LogStr # 
IsString LogStr # 

Methods

fromString :: String -> LogStr #

Generic LogStr # 

Associated Types

type Rep LogStr :: * -> * #

Methods

from :: LogStr -> Rep LogStr x #

to :: Rep LogStr x -> LogStr #

Semigroup LogStr # 
Monoid LogStr # 
FromJSON LogStr # 
type Rep LogStr # 
type Rep LogStr = D1 (MetaData "LogStr" "Katip.Core" "katip-0.5.0.0-5Om1z0bPkZ0A49qyD7iqyp" True) (C1 (MetaCons "LogStr" PrefixI True) (S1 (MetaSel (Just Symbol "unLogStr") NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 Builder)))

logStr :: StringConv a Text => a -> LogStr #

Pack any string-like thing into a LogStr. This will automatically work on String, ByteString, Text and any of the lazy variants.

ls :: StringConv a Text => a -> LogStr #

Shorthand for logStr

showLS :: Show a => a -> LogStr #

Convert any showable type into a LogStr.

data Item a #

This has everything each log message will contain.

Instances

Functor Item # 

Methods

fmap :: (a -> b) -> Item a -> Item b #

(<$) :: a -> Item b -> Item a #

Show a => Show (Item a) # 

Methods

showsPrec :: Int -> Item a -> ShowS #

show :: Item a -> String #

showList :: [Item a] -> ShowS #

Generic (Item a) # 

Associated Types

type Rep (Item a) :: * -> * #

Methods

from :: Item a -> Rep (Item a) x #

to :: Rep (Item a) x -> Item a #

ToJSON a => ToJSON (Item a) # 
FromJSON a => FromJSON (Item a) # 
type Rep (Item a) # 

itemTime :: forall a. Lens' (Item a) UTCTime #

itemSeverity :: forall a. Lens' (Item a) Severity #

itemProcess :: forall a. Lens' (Item a) ProcessID #

itemPayload :: forall a a. Lens (Item a) (Item a) a a #

itemMessage :: forall a. Lens' (Item a) LogStr #

itemLoc :: forall a. Lens' (Item a) (Maybe Loc) #

itemHost :: forall a. Lens' (Item a) HostName #

itemEnv :: forall a. Lens' (Item a) Environment #

itemApp :: forall a. Lens' (Item a) Namespace #

newtype LocShow #

Constructors

LocShow Loc 

Instances

newtype LocJs #

Constructors

LocJs 

Fields

class ToObject a where #

Katip requires JSON objects to be logged as context. This typeclass provides a default instance which uses ToJSON and produces an empty object if toJSON results in any type other than object. If you have a type you want to log that produces an Array or Number for example, you'll want to write an explicit instance here. You can trivially add a ToObject instance for something with a ToJSON instance like:

instance ToObject Foo

Methods

toObject :: a -> Object #

toObject :: ToJSON a => a -> Object #

class ToObject a => LogItem a where #

Payload objects need instances of this class. LogItem makes it so that you can have very verbose items getting logged with lots of extra fields but under normal circumstances, if your scribe is configured for a lower verbosity level, it will only log a selection of those keys. Furthermore, each Scribe can be configured with a different Verbosity level. You could even use registerScribe, unregisterScribe, and clearScribes to at runtime swap out your existing scribes for more verbose debugging scribes if you wanted to.

When defining payloadKeys, don't redundantly declare the same keys for higher levels of verbosity. Each level of verbosity automatically and recursively contains all keys from the level before it.

Minimal complete definition

payloadKeys

Methods

payloadKeys :: Verbosity -> a -> PayloadSelection #

List of keys in the JSON object that should be included in message.

data AnyLogPayload #

Constructors

ToJSON a => AnyLogPayload a 

newtype SimpleLogPayload #

Instances

Semigroup SimpleLogPayload # 
Monoid SimpleLogPayload # 
ToJSON SimpleLogPayload #

A built-in convenience log payload that won't log anything on V0, but will log everything in any other level of verbosity. Intended for easy in-line usage without having to define new log types.

Construct using sl and combine multiple tuples using <> from Monoid.

LogItem SimpleLogPayload # 
ToObject SimpleLogPayload # 

sl :: ToJSON a => Text -> a -> SimpleLogPayload #

Construct a simple log from any JSON item.

payloadObject :: LogItem a => Verbosity -> a -> Object #

Constrain payload based on verbosity. Backends should use this to automatically bubble higher verbosity levels to lower ones.

itemJson :: LogItem a => Verbosity -> Item a -> Value #

Convert log item to its JSON representation while trimming its payload based on the desired verbosity. Backends that push JSON messages should use this to obtain their payload.

data Scribe #

Scribes are handlers of incoming items. Each registered scribe knows how to push a log item somewhere.

Guidelines for writing your own Scribe

Scribes should always take a Severity and Verbosity.

Severity is used to *exclude log messages* that are < the provided Severity. For instance, if the user passes InfoS, DebugS items should be ignored. Katip provides the permitItem utility for this.

Verbosity is used to select keys from the log item's payload. Each LogItem instance describes what keys should be retained for each Verbosity level. Use the payloadObject utility for extracting the keys that should be permitted.

There is no built-in mechanism in katip for telling a scribe that its time to shut down. unregisterScribe merely drops it from the LogEnv. This means there are 2 ways to handle resources as a scribe:

  1. Pass in the resource when the scribe is created. Handle allocation and release of the resource elsewhere. This is what the Handle scribe does.
  2. Return a finalizing function that tells the scribe to shut down. katip-elasticsearch's mkEsScribe returns an IO (Scribe, IO ()). The finalizer will flush any queued log messages and shut down gracefully before returning. This can be hooked into your application's shutdown routine to ensure you never miss any log messages on shutdown.

Constructors

Scribe 

Fields

  • liPush :: forall a. LogItem a => Item a -> IO ()
     
  • scribeFinalizer :: IO ()

    Provide a *blocking* finalizer to call when your scribe is removed. If this is not relevant to your scribe, return () is fine.

data WorkerMessage where #

Constructors

NewItem :: LogItem a => Item a -> WorkerMessage 
PoisonPill :: WorkerMessage 

permitItem :: Severity -> Item a -> Bool #

Should this item be logged given the user's maximum severity?

data LogEnv #

Constructors

LogEnv 

Fields

initLogEnv #

Arguments

:: Namespace

A base namespace for this application

-> Environment

Current run environment (e.g. prod vs. devel)

-> IO LogEnv 

Create a reasonable default InitLogEnv. Uses an AutoUdate with the default settings as the timer. If you are concerned about timestamp precision or event ordering in log outputs like ElasticSearch, you should replace the timer with getCurrentTime

registerScribe #

Arguments

:: Text

Name the scribe

-> Scribe 
-> ScribeSettings 
-> LogEnv 
-> IO LogEnv 

Add a scribe to the list. All future log calls will go to this scribe in addition to the others.

defaultScribeSettings :: ScribeSettings #

Reasonable defaults for a scribe. Buffer size of 4096.

unregisterScribe #

Arguments

:: Text

Name of the scribe

-> LogEnv 
-> LogEnv 

Remove a scribe from the environment. This does *not* finalize the scribe. This mainly only makes sense to use with something like MonadReader's local function to temporarily disavow a single logger for a block of code.

clearScribes :: LogEnv -> LogEnv #

Unregister *all* scribes. Note that this is *not* for closing or finalizing scribes, use closeScribes for that. This mainly only makes sense to use with something like MonadReader's local function to temporarily disavow any loggers for a block of code.

closeScribe #

Arguments

:: Text

Name of the scribe

-> LogEnv 
-> IO LogEnv 

Finalize a scribe. The scribe is removed from the environment, its finalizer is called and it can never be written to again. Note that this will throw any exceptions yoru finalizer will throw, and that LogEnv is immutable, so it will not be removed in that case.

closeScribes :: LogEnv -> IO LogEnv #

Call this at the end of your program. This is a blocking call that stop writing to a scribe's queue, waits for the queue to empty, finalizes each scribe in the log environment and then removes it. Finalizers are all run even if one of them throws, but the exception will be re-thrown at the end.

class MonadIO m => Katip m where #

Monads where katip logging actions can be performed. Katip is the most basic logging monad. You will typically use this directly if you either don't want to use namespaces/contexts heavily or if you want to pass in specific contexts and/or namespaces at each log site.

For something more powerful, look at the docs for KatipContext, which keeps a namespace and merged context. You can write simple functions that add additional namespacing and merges additional context on the fly.

localLogEnv was added to allow for lexically-scoped modifications of the log env that are reverted when the supplied monad completes. katipNoLogging, for example, uses this to temporarily pause log outputs.

Minimal complete definition

getLogEnv, localLogEnv

Methods

getLogEnv :: m LogEnv #

localLogEnv :: (LogEnv -> LogEnv) -> m a -> m a #

Instances

Katip m => Katip (MaybeT m) # 

Methods

getLogEnv :: MaybeT m LogEnv #

localLogEnv :: (LogEnv -> LogEnv) -> MaybeT m a -> MaybeT m a #

Katip m => Katip (ResourceT m) # 
MonadIO m => Katip (KatipT m) # 

Methods

getLogEnv :: KatipT m LogEnv #

localLogEnv :: (LogEnv -> LogEnv) -> KatipT m a -> KatipT m a #

MonadIO m => Katip (KatipContextT m) # 
Katip m => Katip (EitherT s m) # 

Methods

getLogEnv :: EitherT s m LogEnv #

localLogEnv :: (LogEnv -> LogEnv) -> EitherT s m a -> EitherT s m a #

(Katip m, Monoid s) => Katip (WriterT s m) # 

Methods

getLogEnv :: WriterT s m LogEnv #

localLogEnv :: (LogEnv -> LogEnv) -> WriterT s m a -> WriterT s m a #

Katip m => Katip (StateT s m) # 

Methods

getLogEnv :: StateT s m LogEnv #

localLogEnv :: (LogEnv -> LogEnv) -> StateT s m a -> StateT s m a #

Katip m => Katip (ExceptT s m) # 

Methods

getLogEnv :: ExceptT s m LogEnv #

localLogEnv :: (LogEnv -> LogEnv) -> ExceptT s m a -> ExceptT s m a #

Katip m => Katip (StateT s m) # 

Methods

getLogEnv :: StateT s m LogEnv #

localLogEnv :: (LogEnv -> LogEnv) -> StateT s m a -> StateT s m a #

(Katip m, Monoid s) => Katip (WriterT s m) # 

Methods

getLogEnv :: WriterT s m LogEnv #

localLogEnv :: (LogEnv -> LogEnv) -> WriterT s m a -> WriterT s m a #

Katip m => Katip (ReaderT * s m) # 

Methods

getLogEnv :: ReaderT * s m LogEnv #

localLogEnv :: (LogEnv -> LogEnv) -> ReaderT * s m a -> ReaderT * s m a #

(Katip m, Monoid w) => Katip (RWST r w s m) # 

Methods

getLogEnv :: RWST r w s m LogEnv #

localLogEnv :: (LogEnv -> LogEnv) -> RWST r w s m a -> RWST r w s m a #

(Katip m, Monoid w) => Katip (RWST r w s m) # 

Methods

getLogEnv :: RWST r w s m LogEnv #

localLogEnv :: (LogEnv -> LogEnv) -> RWST r w s m a -> RWST r w s m a #

newtype KatipT m a #

A concrete monad you can use to run logging actions. Use this if you prefer an explicit monad transformer stack and adding layers as opposed to implementing Katip for your monad.

Constructors

KatipT 

Fields

Instances

MonadTrans KatipT # 

Methods

lift :: Monad m => m a -> KatipT m a #

MonadTransControl KatipT # 

Associated Types

type StT (KatipT :: (* -> *) -> * -> *) a :: * #

Methods

liftWith :: Monad m => (Run KatipT -> m a) -> KatipT m a #

restoreT :: Monad m => m (StT KatipT a) -> KatipT m a #

MonadBase b m => MonadBase b (KatipT m) # 

Methods

liftBase :: b α -> KatipT m α #

MonadBaseControl b m => MonadBaseControl b (KatipT m) # 

Associated Types

type StM (KatipT m :: * -> *) a :: * #

Methods

liftBaseWith :: (RunInBase (KatipT m) b -> b a) -> KatipT m a #

restoreM :: StM (KatipT m) a -> KatipT m a #

Monad m => Monad (KatipT m) # 

Methods

(>>=) :: KatipT m a -> (a -> KatipT m b) -> KatipT m b #

(>>) :: KatipT m a -> KatipT m b -> KatipT m b #

return :: a -> KatipT m a #

fail :: String -> KatipT m a #

Functor m => Functor (KatipT m) # 

Methods

fmap :: (a -> b) -> KatipT m a -> KatipT m b #

(<$) :: a -> KatipT m b -> KatipT m a #

Applicative m => Applicative (KatipT m) # 

Methods

pure :: a -> KatipT m a #

(<*>) :: KatipT m (a -> b) -> KatipT m a -> KatipT m b #

(*>) :: KatipT m a -> KatipT m b -> KatipT m b #

(<*) :: KatipT m a -> KatipT m b -> KatipT m a #

MonadIO m => MonadIO (KatipT m) # 

Methods

liftIO :: IO a -> KatipT m a #

MonadThrow m => MonadThrow (KatipT m) # 

Methods

throwM :: Exception e => e -> KatipT m a #

MonadCatch m => MonadCatch (KatipT m) # 

Methods

catch :: Exception e => KatipT m a -> (e -> KatipT m a) -> KatipT m a #

MonadMask m => MonadMask (KatipT m) # 

Methods

mask :: ((forall a. KatipT m a -> KatipT m a) -> KatipT m b) -> KatipT m b #

uninterruptibleMask :: ((forall a. KatipT m a -> KatipT m a) -> KatipT m b) -> KatipT m b #

MonadIO m => Katip (KatipT m) # 

Methods

getLogEnv :: KatipT m LogEnv #

localLogEnv :: (LogEnv -> LogEnv) -> KatipT m a -> KatipT m a #

(Monad m, KatipContext m) => KatipContext (KatipT m) # 
type StT KatipT a # 
type StT KatipT a = a
type StM (KatipT m) a # 
type StM (KatipT m) a = ComposeSt KatipT m a

runKatipT :: LogEnv -> KatipT m a -> m a #

Execute KatipT on a log env.

katipNoLogging :: Katip m => m a -> m a #

Disable all scribes for the given monadic action, then restore them afterwards. Works in any Katip monad.

logItem :: (Applicative m, LogItem a, Katip m) => a -> Namespace -> Maybe Loc -> Severity -> LogStr -> m () #

Log with everything, including a source code location. This is very low level and you typically can use logT in its place.

tryWriteTBQueue #

Arguments

:: TBQueue a 
-> a 
-> STM Bool

Did we write?

logF #

Arguments

:: (Applicative m, LogItem a, Katip m) 
=> a

Contextual payload for the log

-> Namespace

Specific namespace of the message.

-> Severity

Severity of the message

-> LogStr

The log message

-> m () 

Log with full context, but without any code location.

logException #

Arguments

:: (Katip m, LogItem a, MonadCatch m, Applicative m) 
=> a

Log context

-> Namespace

Namespace

-> Severity

Severity

-> m b

Main action being run

-> m b 

Perform an action while logging any exceptions that may occur. Inspired by onException.

>>> > logException () mempty ErrorS (error "foo")

logMsg :: (Applicative m, Katip m) => Namespace -> Severity -> LogStr -> m () #

Log a message without any payload/context or code location.

liftLoc :: Loc -> Q Exp #

Lift a location into an Exp.

getLoc :: (?loc :: CallStack) => Maybe Loc #

For use when you want to include location in your logs. This will fill the 'Maybe Loc' gap in logF of this module, and relies on implicit callstacks when available (GHC > 7.8).

logT :: ExpQ #

Loc-tagged logging when using template-haskell.

$(logT) obj mempty InfoS "Hello world"

logLoc :: (Applicative m, LogItem a, Katip m, ?loc :: CallStack) => a -> Namespace -> Severity -> LogStr -> m () #

Loc-tagged logging using implicit-callstacks when available.

This function does not require template-haskell as it automatically uses implicit-callstacks when the code is compiled using GHC > 7.8. Using an older version of the compiler will result in the emission of a log line without any location information, so be aware of it. Users using GHC <= 7.8 may want to use the template-haskell function logT for maximum compatibility.

logLoc obj mempty InfoS "Hello world"