Copyright | Copyright 2022 Shea Levy. |
---|---|
License | Apache-2.0 |
Maintainer | shea@shealevy.com |
Safe Haskell | Safe-Inferred |
Language | Haskell2010 |
This is the primary module needed to write new EventBackend
s.
Synopsis
- data EventBackend m r s = EventBackend {
- newEventImpl :: !(forall f. s f -> m (EventImpl m r f))
- newOnceFlag :: !(m (OnceFlag m))
- data EventImpl m r f = EventImpl {
- referenceImpl :: !r
- addFieldImpl :: !(f -> m ())
- addParentImpl :: !(r -> m ())
- addProximateImpl :: !(r -> m ())
- finalizeImpl :: !(m ())
- failImpl :: !(Maybe SomeException -> m ())
- unitEventBackend :: Applicative m => EventBackend m () s
- pairEventBackend :: Applicative m => EventBackend m a s -> EventBackend m b s -> EventBackend m (a, b) s
- hoistEventBackend :: (Functor m, Functor n) => (forall x. m x -> n x) -> EventBackend m r s -> EventBackend n r s
- narrowEventBackend :: Functor m => (forall f. s f -> t f) -> EventBackend m r t -> EventBackend m r s
- narrowEventBackend' :: Functor m => (forall f. s f -> forall a. (forall g. t g -> (f -> g) -> a) -> a) -> EventBackend m r t -> EventBackend m r s
- newtype OnceFlag m = OnceFlag {
- checkAndSet :: m FlagState
- data FlagState
- runOnce :: Monad m => OnceFlag m -> m () -> m ()
- hoistOnceFlag :: (forall x. f x -> g x) -> OnceFlag f -> OnceFlag g
- alwaysNewOnceFlag :: Applicative m => OnceFlag m
- newOnceFlagMVar :: PrimMonad m => m (OnceFlag m)
Documentation
data EventBackend m r s Source #
A backend for creating Event
s.
Different EventBackend
s will be used to emit instrumentation to
different systems. Multiple backends can be combined with
pairEventBackend
.
A simple EventBackend
for logging to a Handle
can be
created with jsonHandleBackend
.
Typically the entrypoint for some eventuo11y-instrumented code will
take an EventBackend
, polymorphic in r
and possibly m
. Calling
code can use subEventBackend
to place the resulting
events in its hierarchy.
From an EventBackend
, new events can be created via selectors
(of type s f
for some field type f
), typically with the
resource-safe allocation functions.
Selectors are values which designate the general category of event
being created, as well as the type of fields that can be added to it.
For example, a web service's selector type may have a ServicingRequest
constructor, whose field type includes a ResponseCode
constructor which
records the HTTP status code.
Selectors are intended to be of a domain specific type per unit of
functionality within an instrumented codebase, implemented as a GADT
(but see DynamicEventSelector
for a generic option).
Implementations must ensure that EventBackend
s and their underlying Event
s
are safe to use across threads.
m
- The monad we're instrumenting in.
r
- The type of event references used in this
EventBackend
. Seereference
. s
- The type of event selectors.
EventBackend | |
|
The internal implementation of an Event
.
All fields have corresponding event manipulation functions,
except that finalizeImpl
and failImpl
can assume that they will only ever be called
once (i.e., EventImpl
implementations do not have to implement locking internally).
EventImpl | |
|
unitEventBackend :: Applicative m => EventBackend m () s Source #
A no-op EventBackend
.
This can be used if calling instrumented code from an un-instrumented context, or to purposefully ignore instrumentation from some call.
unitEventBackend
is the algebraic unit of pairEventBackend
.
pairEventBackend :: Applicative m => EventBackend m a s -> EventBackend m b s -> EventBackend m (a, b) s Source #
An EventBackend
which sequentially generates Event
s in the two given EventBackend
s.
This can be used to emit instrumentation in multiple ways (e.g. logs to grafana and metrics on a prometheus HTML page).
:: (Functor m, Functor n) | |
=> (forall x. m x -> n x) | Natural transformation from |
-> EventBackend m r s | |
-> EventBackend n r s |
Hoist an EventBackend
along a given natural transformation into a new monad.
:: Functor m | |
=> (forall f. s f -> t f) | Inject a narrow selector into the wider selector type. |
-> EventBackend m r t | |
-> EventBackend m r s |
Narrow an EventBackend
to a new selector type via a given injection function.
A typical usage, where component A calls component B, would be to have A's selector
type have a constructor to take any value of B's selector type (and preserve the field)
and then call narrowEventBackend
with that constructor when invoking functions in B.
See narrowEventBackend'
for a more general, if unweildy, variant.
:: Functor m | |
=> (forall f. s f -> forall a. (forall g. t g -> (f -> g) -> a) -> a) | Simultaneously inject a narrow selector into the wider selector type and the narrow selector's field into the wider selector's field type. |
-> EventBackend m r t | |
-> EventBackend m r s |
Narrow an EventBackend
to a new selector type via a given injection function.
See narrowEventBackend
for a simpler, if less general, variant.
OnceFlags
Generic helper to make operations idempotent.
A flag to ensure only one operation from some class is performed, once.
Typically consumed via runOnce
OnceFlag | |
|
The state of a OnceFlag
NewlySet | The flag was not set, but is now |
AlreadySet | The flag was already set |
runOnce :: Monad m => OnceFlag m -> m () -> m () Source #
Run an operation if no other operations using this
OnceFlag
have run.
Hoist a OnceFlag
along a given natural transformation into a new monad.
alwaysNewOnceFlag :: Applicative m => OnceFlag m Source #