Emitting events
Emitting an event is two steps: build a MessagePack payload, then hand it and an event type to the kernel. This guide shows both; event.h and msgpack.h are the full references. Emitting requires SeAuditPrivilege.
Choose the event type and fields first: Naming and shaping your events covers that, and the examples below use its backup-tool event.
Ask whether the type is on #
An administrator can switch event types on and off in the registry, and an emitter must not write a type that is switched off (PGSS §6.9). Open a policy handle once, and ask it before building each payload. The tier is the one your fragment declares for the type:
peios_event_policy *policy = ; /* once, at startup */
static const char type = "org.example.backup.snapshot.created";
if
return; /* off: build nothing */
The handle caches its answers and watches the registry, so asking costs little. A change the administrator commits applies to your next decision. Essential types are always on. See the emission policy for the details.
Build the payload #
Use the MessagePack writer to encode a single top-level value: a map whose nested maps spell the field paths. This payload carries outcome.success:
peios_mp_writer *w = ;
; /* {outcome: {success: true}} */
;
;
; ;
const void *payload;
ssize_t plen = ; /* validates as it borrows */
if
peios_mp_writer_bytes validates that what you built is exactly one well-formed value, so a non-negative return means the payload is emit-ready. (Remember a map of n needs 2*n values — one per key and value.)
Emit it #
static const char type = "org.example.backup.snapshot.created";
int rc = ;
;
if
The event type is length-counted UTF-8 and must be non-zero length. It isn't NUL-terminated on the wire, which is why the example passes sizeof type - 1. On success the kernel stamps the trusted metadata (timestamp, sequence, identity GUIDs) and sets origin_class = userspace, which queries see as emitter.class; you don't provide any of that, and your payload must not repeat it.
Validating untrusted payloads first #
If a payload's shape comes from dynamic or untrusted input, validate it in userspace before emitting so you handle the failure on your terms rather than as an EINVAL from the kernel:
if
The validator's acceptance matches the kernel's emit-time check at that depth bound.
Emitting in batches #
A high-rate producer should batch. peios_event_emit_batch emits many events in one call, so a single timestamp capture, identity capture, and consumer wake cover the whole set:
struct peios_event_entry entries = ;
uint32_t emitted = 0;
int rc = ;
if
count must be in [1, KMES_BATCH_MAX_ENTRIES]. On failure, errno is the reason the first failing entry failed and emitted tells you how many succeeded before it, so you know exactly where to resume. One caveat: rate-limiting is all-or-nothing for a batch — an EAGAIN emits none of it, so on EAGAIN back off and retry the whole batch.
Next #
- Consuming events — the other side of the pipe.
msgpack.hreference — the full encoder, including containers, extensions, and raw splicing.