HORIZON HASKELLDocslts/ghc-9.10.x248f8f02026-10-05Search names, modules, packages, or :: a typeCtrl K

GHC 9.10.3 · lts/ghc-9.10.x · 248f8f0 · 2026-10-05

Modulekatip-0.8.8.0Haskell2010

Katip.Core

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

  • 20 types
  • 3 classes
  • 60 values
  • Packagekatip-0.8.8.0
  • Exports83
  • LanguageHaskell2010
  • LicenceBSD-3-Clause
  • SourceCore.hs
newtypenewtype 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

Instances12Eq, Ord, Read, Show, IsString, Generic, …
newtypenewtype Environment
#

Application environment, like prod, devel, testing.

Instances9Eq, Ord, Read, Show, IsString, Generic, …
datadata Severity
#

Constructors

Instances11Bounded, Enum, Eq, Ord, Read, Show, …
datadata 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.

Instances11Bounded, Enum, Eq, Ord, Read, Show, …
newtypenewtype LogStr
#

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

Constructors

Instances8Eq, Show, IsString, Generic, Semigroup, Monoid, …
datadata Item a
#
Instances7Functor, Eq, Show, Generic, FromJSON, ToJSON, …
classclass 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

Instances4ToObject
classclass 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.

Methods

Instances3LogItem
newtypenewtype SimpleLogPayload
#
Instances5Semigroup, Monoid, ToJSON, LogItem, ToObject
valuepayloadObject :: LogItem a => Verbosity -> a -> Object
#

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

valueitemJson :: 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.

typetype PermitFunc = forall a. Item a -> IO Bool
#

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 lower than the provided Severity. For instance, if the user passes InfoS, DebugS items should be ignored. Katip provides the permitItem utility for this. The user or the scribe may use permitAND and permitOR to further customize this filtering, even dynamically if they wish to.

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 written.

Scribes provide a finalizer IO action (scribeFinalizer) that is meant to synchronously flush any remaining writes and clean up any resources acquired when the scribe was created. Internally, katip keeps a buffer for each scribe's writes. When closeScribe or closeScribes is called, that buffer stops accepting new log messages and after the last item in its buffer is sent to liPush, calls the finalizer. Thus, when the finalizer returns, katip can assume that all resources are cleaned up and all log messages are durably written.

While katip internally buffers messages per ScribeSettings, it sends them one at a time to the scribe. Depending on the scribe itself, it may make sense for that scribe to keep its own internal buffer to batch-send logs if writing items one at a time is not efficient. The scribe implementer must be sure that on finalization, all writes are committed synchronously.

Signature of a function passed to Scribe constructor and mkScribe* functions that decides which messages to be logged. Typically filters based on Severity, but can be combined with other, custom logic with permitAND and permitOR

datadata Scribe
#

Constructors

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

      How do we write an item to the scribe's output?

    • scribeFinalizer :: IO ()

      Provide a blocking finalizer to call when your scribe is removed. All pending writes should be flushed synchronously. If this is not relevant to your scribe, return () is fine.

    • scribePermitItem :: PermitFunc

      Provide a filtering function to allow the item to be logged, or not. It can check Severity or some string in item's body. The initial value of this is usually created from permitItem. Scribes and users can customize this by ANDing or ORing onto the default with permitAND or permitOR

Instances2Semigroup, Monoid
  • Semigroup ScribeDefined in katip-0.8.8.0 · Katip.Core

    Combine two scribes. Publishes to the left scribe if the left would permit the item and to the right scribe if the right would permit the item. Finalizers are called in sequence from left to right.

  • Monoid ScribeDefined in katip-0.8.8.0 · Katip.Core
datadata LogEnv
#

Constructors

valueinitLogEnv
  1. :: Namespace

    A base namespace for this application

  2. -> Environment

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

  3. -> IO LogEnv
#

Create a reasonable default InitLogEnv. Uses an AutoUpdate which updates the timer every 1ms. If you need even more timestamp precision at the cost of performance, consider setting _logEnvTimer with getCurrentTime.

valueregisterScribe
  1. :: Text

    Name the scribe

  2. -> Scribe
  3. -> ScribeSettings
  4. -> LogEnv
  5. -> IO LogEnv
#

Add a scribe to the list. All future log calls will go to this scribe in addition to the others. Writes will be buffered per the ScribeSettings to prevent slow scribes from slowing down logging. Writes will be dropped if the buffer fills.

valueunregisterScribe
  1. :: Text

    Name of the scribe

  2. -> LogEnv
  3. -> 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.

valueclearScribes :: 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.

valuecloseScribe
  1. :: Text

    Name of the scribe

  2. -> LogEnv
  3. -> IO LogEnv
#

Finalize a scribe. The scribe is removed from the environment, its finalizer is called so that it can never be written to again and all pending writes are flushed. 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.

valuecloseScribes :: 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.

classclass MonadIO m => Katip (m :: Type -> Type) 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.

Methods

Instances13Katip, …
newtypenewtype KatipT (m :: Type -> Type) 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

Instances18MonadTrans, MonadTransControl, MonadBase, MonadBaseControl, Monad, Functor, …
valuekatipNoLogging :: Katip m => m a -> m a
#

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

valuelogKatipItem :: (Applicative m, LogItem a, Katip m) => Item a -> m ()
#

Log already constructed Item. This is the lowest level function that other log* functions use. It can be useful when implementing centralised logging services.

valuelogException
  1. :: (Katip m, LogItem a, MonadCatch m, Applicative m)
  2. => a

    Log context

  3. -> Namespace

    Namespace

  4. -> Severity

    Severity

  5. -> m b

    Main action being run

  6. -> m b
#

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

Example1 expression
> logException () mempty ErrorS (error "foo")
valuegetLoc :: HasCallStack => 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).

valuelogT :: ExpQ
#

Loc-tagged logging when using template-haskell.

$(logT) obj mempty InfoS "Hello world"
valuelogLoc
  1. :: (Applicative m, LogItem a, Katip m, HasCallStack)
  2. => a
  3. -> Namespace
  4. -> Severity
  5. -> LogStr
  6. -> m ()
#

Loc-tagged logging using GHC.Stack 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"