packages feed

benign-katip (empty) → 0.1.0

raw patch · 2 files changed

+116/−0 lines, 2 filesdep +basedep +benigndep +katip

Dependencies added: base, benign, katip

Files

+ benign-katip.cabal view
@@ -0,0 +1,33 @@+cabal-version: 1.12++-- This file has been generated from package.yaml by hpack version 0.38.0.+--+-- see: https://github.com/sol/hpack++name:           benign-katip+version:        0.1.0+synopsis:       A Benign backend for the Katip library+description:    see README.md.+homepage:       https://github.com/aspiwack/haskell-benign#readme+bug-reports:    https://github.com/aspiwack/haskell-benign/issues+author:         Arnaud Spiwack+maintainer:     arnaud@spiwack.net+copyright:      MIT+license:        MIT+build-type:     Simple++source-repository head+  type: git+  location: https://github.com/aspiwack/haskell-benign++library+  exposed-modules:+      Benign.Katip+  hs-source-dirs:+      src+  ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wnoncanonical-monad-instances -Wredundant-constraints+  build-depends:+      base <4.22+    , benign+    , katip+  default-language: Haskell2010
+ src/Benign/Katip.hs view
@@ -0,0 +1,83 @@+{-# LANGUAGE GHC2021 #-}++-- | This module is a small wrapper around+-- [Katip](https://hackage.haskell.org/package/katip) to allow logging in pure+-- code.+--+-- The wrapper is a little primitive still and you will have to handle the+-- transition from IO code to pure code manually. Pull requests are, of course,+-- welcome.+module Benign.Katip+  ( withKatipContext,+    withKatipNamespace,+    withKatip,+    logLocM,+  )+where++import Benign qualified+import GHC.Stack+import Katip qualified+import System.IO.Unsafe (unsafePerformIO)+import Prelude++katipEnv :: Benign.Field Katip.LogEnv+katipEnv = unsafePerformIO Benign.newField+{-# NOINLINE katipEnv #-}++katipContext :: Benign.Field Katip.LogContexts+katipContext = unsafePerformIO Benign.newField+{-# NOINLINE katipContext #-}++katipNamespace :: Benign.Field Katip.Namespace+katipNamespace = unsafePerformIO Benign.newField+{-# NOINLINE katipNamespace #-}++-- | See 'Katip.katipAddContext'.+withKatipContext :: (Katip.LogItem i) => i -> Benign.Strat a -> a -> a+withKatipContext item = Benign.withAltering katipContext (<> Just (Katip.liftPayload item))++-- | See 'Katip.katipAddNamespace'.+withKatipNamespace :: Katip.Namespace -> Benign.Strat a -> a -> a+withKatipNamespace namespace = Benign.withAltering katipNamespace (<> Just namespace)++-- | Within this computation, Katip is configured for pure code.+withKatip ::+  (Katip.LogItem c) =>+  Katip.LogEnv ->+  c ->+  Katip.Namespace ->+  Benign.Strat a ->+  IO a ->+  IO a+withKatip env ctx namespace strat =+  Benign.withSettingIO' katipEnv env+    . Benign.withSettingIO' katipContext (Katip.liftPayload ctx)+    . Benign.withSettingIO katipNamespace namespace strat++-- | @'logLocM' s msg a@ logs a an event, like Katip's 'Katip.logLocM', before+-- evaluating @a@.+logLocM :: forall a. (HasCallStack) => Katip.Severity -> Katip.LogStr -> a -> a+logLocM severity str = withFrozenCallStack spanLog+  where+    -- The whole purpose of naming `span` is to freeze the call stack. It's+    -- important to freeze the call site, so that the log is recorded as+    -- happening on the line where `logLocM` was called, not on this file. But+    -- since `HasCallStack` is magical, it's quite possible for the type system+    -- to “lose track” of the current `HasCallStack` and create a new one from+    -- scratch. This would be invisible. I tried to harden this function by+    -- declaring type signatures everywhere. I haven't tested it yet though. It+    -- may be wrong.+    spanLog :: (HasCallStack) => a -> a+    spanLog = Benign.unsafeSpanBenign doLog (return ()) Benign.whnf++    doLog :: (HasCallStack) => IO ()+    doLog = do+      -- Making an intermediary `KatipContextT` is a little roundabout, but it's+      -- easier than reaching to Katip's internals.+      --+      -- TODO: catch errors+      Just env <- Benign.lookupLexicalState katipEnv+      Just ctx <- Benign.lookupLexicalState katipContext+      Just namespace <- Benign.lookupLexicalState katipNamespace+      Katip.runKatipContextT env ctx namespace $ Katip.logLocM severity str