Tag Enrichers
Named tags can be given at every append call, but some tags belong to the surroundings of the append rather than to the code that does it. Chronicle resolves the tags of every event in one step, used by every append path: single appends, AppendMany, and units of work.
For each event the tags are resolved in this order and merged without duplicates:
- The static
[Tag]tags of the event type. - The tags already on the event, including those given at the call site.
- The built-in enrichers: the ambient scope and
[Audience]properties. - Your own
IEventTagEnricherimplementations.
For a unit of work this happens when the event is added, not when the unit commits.
Writing an enricher
Section titled “Writing an enricher”Implement IEventTagEnricher. Enrichers are discovered automatically, resolved through dependency injection, and all of them run for every event. They must be pure, synchronous and additive: they can add tags, never remove or change them.
using Cratis.Chronicle;
public class EnrichersTenantRegionTagEnricher(IRegionLookup regions) : IEventTagEnricher{ public IEnumerable<NamedTag> GetTags(EventTagContext context) { if (context.EventSequenceId != Cratis.Chronicle.EventSequences.EventSequenceId.Outbox) { return []; }
return [new NamedTag(new TagName("region"), regions.For(context.EventSourceId.Value))]; }}
public interface IRegionLookup{ string For(string eventSourceId);}The EventTagContext gives you the event store name, the event sequence, the event source id, the event type, the event itself and the tags it already has.
Ambient scopes
Section titled “Ambient scopes”EventTags.Scope(name, value) stamps a tag on every event appended inside the scope, without the appending code having to know. The scope flows with the async execution context and is closed by disposing it.
using Cratis.Chronicle;using Cratis.Chronicle.Events;
[EventType]public record EnrichersOrderPlaced(string OrderId);
public static class EnrichersAmbientScope{ public static async Task Place(IEventStore eventStore) { // Every event appended inside the scope gets region=eu, without the append code knowing. using var scope = EventTags.Scope("region", "eu"); await eventStore.EventLog.Append("order-1", new EnrichersOrderPlaced("order-1")); }}Nested scopes add up. EventTags.Audience(value) is the same with the audience name; see Audiences for where it applies.