eventuo11y 0.7.0.0 → 0.7.1.0
raw patch · 3 files changed
+214/−1 lines, 3 filesdep +timePVP ok
version bump matches the API change (PVP)
Dependencies added: time
API changes (from Hackage documentation)
+ Observe.Event.Render.InMemory: AddField :: !f -> EventAction f
+ Observe.Event.Render.InMemory: AppendVectorEffects :: !forall a. m (appvec a) -> !forall a. appvec a -> a -> m () -> AppendVectorEffects m appvec
+ Observe.Event.Render.InMemory: Finalize :: !Maybe SomeException -> EventAction f
+ Observe.Event.Render.InMemory: InMemoryEffects :: !AppendVectorEffects m appvec -> !TimestampEffects m ts -> InMemoryEffects m appvec ts
+ Observe.Event.Render.InMemory: ListAppendVector :: MutVar (PrimState m) [a] -> ListAppendVector m a
+ Observe.Event.Render.InMemory: MemoryEvent :: !NewEventArgs (MemoryEvent m appvec ts s) s f -> !ts -> !Maybe (appvec (TimedEventAction ts f)) -> MemoryEvent m appvec ts s
+ Observe.Event.Render.InMemory: TimedEventAction :: !ts -> !EventAction f -> TimedEventAction ts f
+ Observe.Event.Render.InMemory: TimestampEffects :: m ts -> TimestampEffects m ts
+ Observe.Event.Render.InMemory: [act] :: TimedEventAction ts f -> !EventAction f
+ Observe.Event.Render.InMemory: [appendVectorEffects] :: InMemoryEffects m appvec ts -> !AppendVectorEffects m appvec
+ Observe.Event.Render.InMemory: [appendVector] :: AppendVectorEffects m appvec -> !forall a. appvec a -> a -> m ()
+ Observe.Event.Render.InMemory: [dynamicValues] :: MemoryEvent m appvec ts s -> !Maybe (appvec (TimedEventAction ts f))
+ Observe.Event.Render.InMemory: [getTimestamp] :: TimestampEffects m ts -> m ts
+ Observe.Event.Render.InMemory: [initArgs] :: MemoryEvent m appvec ts s -> !NewEventArgs (MemoryEvent m appvec ts s) s f
+ Observe.Event.Render.InMemory: [newVector] :: AppendVectorEffects m appvec -> !forall a. m (appvec a)
+ Observe.Event.Render.InMemory: [start] :: MemoryEvent m appvec ts s -> !ts
+ Observe.Event.Render.InMemory: [timestampEffects] :: InMemoryEffects m appvec ts -> !TimestampEffects m ts
+ Observe.Event.Render.InMemory: [when] :: TimedEventAction ts f -> !ts
+ Observe.Event.Render.InMemory: data AppendVectorEffects m appvec
+ Observe.Event.Render.InMemory: data EventAction f
+ Observe.Event.Render.InMemory: data InMemoryEffects m appvec ts
+ Observe.Event.Render.InMemory: data MemoryEvent m appvec ts s
+ Observe.Event.Render.InMemory: data TimedEventAction ts f
+ Observe.Event.Render.InMemory: dummyTimestampEffects :: Applicative m => TimestampEffects m ()
+ Observe.Event.Render.InMemory: hoistAppendVectorEffects :: (forall x. m x -> n x) -> AppendVectorEffects m appvec -> AppendVectorEffects n appvec
+ Observe.Event.Render.InMemory: hoistInMemoryEffects :: (forall x. m x -> n x) -> InMemoryEffects m appvec ts -> InMemoryEffects n appvec ts
+ Observe.Event.Render.InMemory: hoistTimestampEffects :: (forall x. m x -> n x) -> TimestampEffects m ts -> TimestampEffects n ts
+ Observe.Event.Render.InMemory: inMemoryBackend :: Monad m => InMemoryEffects m appvec ts -> EventBackend m (MemoryEvent m appvec ts s) s
+ Observe.Event.Render.InMemory: ioTimestampEffects :: TimestampEffects IO UTCTime
+ Observe.Event.Render.InMemory: listAppendVectorEffects :: PrimMonad m => AppendVectorEffects m (ListAppendVector m)
+ Observe.Event.Render.InMemory: listInMemoryBackend :: (PrimMonad m, MonadIO m) => EventBackend m (MemoryEvent m (ListAppendVector m) UTCTime s) s
+ Observe.Event.Render.InMemory: listInMemoryEffects :: (PrimMonad m, MonadIO m) => InMemoryEffects m (ListAppendVector m) UTCTime
+ Observe.Event.Render.InMemory: newtype ListAppendVector m a
+ Observe.Event.Render.InMemory: newtype TimestampEffects m ts
+ Observe.Event.Render.InMemory: timelessListInMemoryBackend :: PrimMonad m => EventBackend m (MemoryEvent m (ListAppendVector m) () s) s
+ Observe.Event.Render.InMemory: timelessListInMemoryEffects :: PrimMonad m => InMemoryEffects m (ListAppendVector m) ()
Files
- CHANGELOG.md +4/−0
- eventuo11y.cabal +3/−1
- src/Observe/Event/Render/InMemory.hs +207/−0
CHANGELOG.md view
@@ -1,5 +1,9 @@ # Revision history for eventuo11y +## 0.7.1.0 -- 2023-01-14++- Add `Observe.Event.Render.InMemory`+ ## 0.7.0.0 -- 2023-01-13 - Use `NewEventArgs` as the basic way to initialize a new `Event`.
eventuo11y.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: eventuo11y-version: 0.7.0.0+version: 0.7.1.0 synopsis: An event-oriented observability library description: Instrument your Haskell codebase with wide, semantically meaningful events.@@ -62,12 +62,14 @@ Observe.Event.Backend Observe.Event.Class Observe.Event.Explicit+ Observe.Event.Render.InMemory build-depends: , base ^>= { 4.14, 4.16, 4.17 } , exceptions ^>= { 0.10 } , general-allocate ^>= { 0.2 } , primitive ^>= { 0.7 }+ , time ^>= { 1.11, 1.12 } , transformers ^>= { 0.5, 0.6 } , transformers-base ^>= { 0.4 } , monad-control ^>= { 1.0 }
+ src/Observe/Event/Render/InMemory.hs view
@@ -0,0 +1,207 @@+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE StandaloneKindSignatures #-}++-- |+-- Description : EventBackend for rendering events as Haskell values+-- Copyright : Copyright 2023 Shea Levy.+-- License : Apache-2.0+-- Maintainer : shea@shealevy.com+module Observe.Event.Render.InMemory+ ( listInMemoryBackend,+ timelessListInMemoryBackend,+ inMemoryBackend,++ -- * MemoryEvent+ MemoryEvent (..),+ TimedEventAction (..),+ EventAction (..),++ -- * Effects++ -- ** InMemoryEffects+ InMemoryEffects (..),+ hoistInMemoryEffects,+ listInMemoryEffects,+ timelessListInMemoryEffects,++ -- ** AppendVectorEffects+ AppendVectorEffects (..),+ hoistAppendVectorEffects,+ ListAppendVector (..),+ listAppendVectorEffects,++ -- ** TimestampEffects+ TimestampEffects (..),+ hoistTimestampEffects,+ dummyTimestampEffects,+ ioTimestampEffects,+ )+where++import Control.Exception+import Control.Monad.IO.Class+import Control.Monad.Primitive+import Data.Kind+import Data.Primitive.MutVar+import Data.Time.Clock+import Observe.Event.Backend++-- | An 'EventBackend' whose 'Event's are essentially plain Haskell values.+--+-- The 'reference' of an 'Event' from this 'EventBackend' will be a 'MemoryEvent',+-- which can be examined to extract information about the 'Event'.+listInMemoryBackend :: (PrimMonad m, MonadIO m) => EventBackend m (MemoryEvent m (ListAppendVector m) UTCTime s) s+listInMemoryBackend = inMemoryBackend listInMemoryEffects++-- | An 'EventBackend' whose 'Event's are essentially plain Haskell values.+--+-- The 'reference' of an 'Event' from this 'EventBackend' will be a 'MemoryEvent',+-- which can be examined to extract information about the 'Event'.+timelessListInMemoryBackend :: (PrimMonad m) => EventBackend m (MemoryEvent m (ListAppendVector m) () s) s+timelessListInMemoryBackend = inMemoryBackend timelessListInMemoryEffects++-- | An 'EventBackend' whose 'Event's are essentially plain Haskell values.+--+-- The 'reference' of an 'Event' from this 'EventBackend' will be a 'MemoryEvent',+-- which can be examined to extract information about the 'Event'.+--+-- [@appvec@]: An append-only vector type, see 'AppendVectorEffects'+-- [@ts@]: A timestamp, see 'TimestampEffects'+inMemoryBackend :: (Monad m) => InMemoryEffects m appvec ts -> EventBackend m (MemoryEvent m appvec ts s) s+inMemoryBackend InMemoryEffects {..} =+ EventBackend+ { newEvent = \initArgs -> do+ start <- getTimestamp+ dynamicValues <- newVector+ pure $+ Event+ { reference = MemoryEvent {dynamicValues = Just dynamicValues, ..},+ addField = \f -> do+ when <- getTimestamp+ appendVector dynamicValues $ TimedEventAction {act = AddField f, ..},+ finalize = \me -> do+ when <- getTimestamp+ appendVector dynamicValues $ TimedEventAction {act = Finalize me, ..}+ },+ emitImmediateEvent = \initArgs -> do+ start <- getTimestamp+ pure $ MemoryEvent {dynamicValues = Nothing, ..}+ }+ where+ AppendVectorEffects {..} = appendVectorEffects+ TimestampEffects {..} = timestampEffects++-- | An plain data type representing an 'Event'+--+-- [@appvec@]: An append-only vector type, see 'AppendVectorEffects'+-- [@ts@]: A timestamp, see 'TimestampEffects'+type MemoryEvent :: (Type -> Type) -> (Type -> Type) -> Type -> (Type -> Type) -> Type+data MemoryEvent m appvec ts s = forall f.+ MemoryEvent+ { -- | The arguments the 'Event' was initialized with+ initArgs :: !(NewEventArgs (MemoryEvent m appvec ts s) s f),+ -- | The start time of the 'Event'+ start :: !ts,+ -- | Event information added during the event's lifecycle+ --+ -- 'Nothing' if this was the result of 'emitImmediateEvent' and thus had no lifecycle+ dynamicValues :: !(Maybe (appvec (TimedEventAction ts f)))+ }++-- | An action that occurred during an 'Event' at some time.+--+-- [@ts@]: A timestamp, see 'TimestampEffects'+data TimedEventAction ts f = TimedEventAction+ { -- | When the event occurred+ when :: !ts,+ -- | The action that occurred+ act :: !(EventAction f)+ }++-- | An action on an 'Event'+data EventAction f+ = -- | A field was added with 'addField'+ AddField !f+ | -- | The 'Event' was finalized with 'finalize'+ Finalize !(Maybe SomeException)++-- | Monadic effects needed to construct an 'inMemoryBackend'+--+-- [@appvec@]: An append-only vector type, see 'AppendVectorEffects'+-- [@ts@]: A timestamp, see 'TimestampEffects'+data InMemoryEffects m appvec ts = InMemoryEffects+ { -- | Manipulate append-only vectors+ appendVectorEffects :: !(AppendVectorEffects m appvec),+ -- | Get timestamps+ timestampEffects :: !(TimestampEffects m ts)+ }++-- | Hoist 'InMemoryEffects' along a given natural transformation into a new monad+hoistInMemoryEffects :: (forall x. m x -> n x) -> InMemoryEffects m appvec ts -> InMemoryEffects n appvec ts+hoistInMemoryEffects nt (InMemoryEffects {..}) =+ InMemoryEffects+ { appendVectorEffects = hoistAppendVectorEffects nt appendVectorEffects,+ timestampEffects = hoistTimestampEffects nt timestampEffects+ }++-- | 'InMemoryEffects' based on 'listAppendVectorEffects' and 'ioTimestampEffects'.+listInMemoryEffects :: (PrimMonad m, MonadIO m) => InMemoryEffects m (ListAppendVector m) UTCTime+listInMemoryEffects =+ InMemoryEffects+ { appendVectorEffects = listAppendVectorEffects,+ timestampEffects = hoistTimestampEffects liftIO ioTimestampEffects+ }++-- | 'InMemoryEffects' based on 'listAppendVectorEffects' with meaningless timestamps.+timelessListInMemoryEffects :: (PrimMonad m) => InMemoryEffects m (ListAppendVector m) ()+timelessListInMemoryEffects =+ InMemoryEffects+ { appendVectorEffects = listAppendVectorEffects,+ timestampEffects = dummyTimestampEffects+ }++-- | Monadic effects to manipulate append-only vectors.+data AppendVectorEffects m appvec = AppendVectorEffects+ { -- | Create a new vector+ newVector :: !(forall a. m (appvec a)),+ -- | Append a value to a vector+ appendVector :: !(forall a. appvec a -> a -> m ())+ }++-- | Hoist 'AppendVectorEffects' along a given natural transformation into a new monad+hoistAppendVectorEffects :: (forall x. m x -> n x) -> AppendVectorEffects m appvec -> AppendVectorEffects n appvec+hoistAppendVectorEffects nt (AppendVectorEffects {..}) =+ AppendVectorEffects+ { newVector = nt $ newVector,+ appendVector = \v -> nt . appendVector v+ }++-- | An append-only vector in some 'PrimMonad' based on lists.+newtype ListAppendVector m a = ListAppendVector (MutVar (PrimState m) [a])++-- | 'AppendVectorEffects' in some 'PrimMonad' based on lists.+listAppendVectorEffects :: (PrimMonad m) => AppendVectorEffects m (ListAppendVector m)+listAppendVectorEffects =+ AppendVectorEffects+ { newVector = ListAppendVector <$> newMutVar [],+ appendVector = \(ListAppendVector v) x -> atomicModifyMutVar v (\l -> (x : l, ()))+ }++-- | Monadic effects to manage timestamps.+newtype TimestampEffects m ts = TimestampEffects+ { getTimestamp :: m ts+ }++-- | Hoist 'TimestampEffects' along a given natural transformation into a new monad+hoistTimestampEffects :: (forall x. m x -> n x) -> TimestampEffects m ts -> TimestampEffects n ts+hoistTimestampEffects nt (TimestampEffects {..}) = TimestampEffects $ nt getTimestamp++-- | 'TimestampEffects' with meaningless timestamps.+dummyTimestampEffects :: (Applicative m) => TimestampEffects m ()+dummyTimestampEffects = TimestampEffects $ pure ()++-- | 'TimestampEffects' using the system clock+ioTimestampEffects :: TimestampEffects IO UTCTime+ioTimestampEffects = TimestampEffects getCurrentTime