Projection with event context values
Event context contains metadata about each event, such as when it occurred, its sequence number, and causation information. Projections can access these values to enrich read models with event metadata.
Available event context properties
Section titled “Available event context properties”The EventContext contains the following properties you can map to:
EventSourceId- The identifier of the event source that produced the eventSequenceNumber- The position of the event in the event sequenceOccurred- When the event occurred (timestamp)EventType- Information about the event typeEventSourceType- The type of the event sourceEventStreamType- The type of the event streamEventStreamId- The identifier of the event streamCorrelationId- The correlation identifier linking related operationsCausation- Information about what caused this eventCausedBy- Identity information about who caused the event
Mapping to event source ID
Section titled “Mapping to event source ID”Use ToEventSourceId() to map the event source ID to a property:
using Cratis.Chronicle.Projections;
public class DecEventContextUserActivityProjection : IProjectionFor<DecEventContextUserActivity>{ public void Define(IProjectionBuilderFor<DecEventContextUserActivity> builder) => builder .From<DecEventContextUserLoggedIn>(_ => _ .Set(m => m.UserId).ToEventSourceId() .Set(m => m.LastLogin).ToEventContextProperty(c => c.Occurred)) .From<DecEventContextUserPerformedAction>(_ => _ .Set(m => m.UserId).ToEventSourceId() .Set(m => m.LastActivity).ToEventContextProperty(c => c.Occurred));}Kotlin does not support this workflow yet.Java does not support this workflow yet.defmodule MyApp.Projections.DecEventContextUserActivityProjection do use Chronicle.Projections.Projection, model: MyApp.ReadModels.DecEventContextUserActivity
alias MyApp.Events.{DecEventContextUserLoggedIn, DecEventContextUserPerformedAction}
from DecEventContextUserLoggedIn, set: [ user_id: :event_source_id, last_login: :occurred ]
from DecEventContextUserPerformedAction, set: [ user_id: :event_source_id, last_activity: :occurred ]endimport { IProjectionBuilderFor, IProjectionFor, projection } from '@cratis/chronicle';
@projection()class DecEventContextUserActivityProjection implements IProjectionFor<DecEventContextUserActivity> { define(builder: IProjectionBuilderFor<DecEventContextUserActivity>): void { builder .from(DecEventContextUserLoggedIn, _ => _ .set(m => m.userId).toEventSourceId() .set(m => m.lastLogin).toEventContextProperty('occurred')) .from(DecEventContextUserPerformedAction, _ => _ .set(m => m.userId).toEventSourceId() .set(m => m.lastActivity).toEventContextProperty('occurred')); }}Mapping to event context properties
Section titled “Mapping to event context properties”Use ToEventContextProperty() to map any event context property:
using Cratis.Chronicle.Events;using Cratis.Chronicle.Projections;
[EventType]public record DecEventContextUserAction(string UserId, string ActionType);
public class DecEventContextAuditTrailProjection : IProjectionFor<DecEventContextAuditEntry>{ public void Define(IProjectionBuilderFor<DecEventContextAuditEntry> builder) => builder .AutoMap() .From<DecEventContextUserAction>(_ => _ .Set(m => m.EventId).ToEventContextProperty(c => c.SequenceNumber) .Set(m => m.OccurredAt).ToEventContextProperty(c => c.Occurred) .Set(m => m.CorrelationId).ToEventContextProperty(c => c.CorrelationId));}Kotlin does not support this workflow yet.Java does not support this workflow yet.defmodule MyApp.Events.DecEventContextUserAction do use Chronicle.Events.EventType, id: "dec-event-context-user-action"
defstruct [:user_id, :action_type]end
defmodule MyApp.Projections.DecEventContextAuditTrailProjection do use Chronicle.Projections.Projection, model: MyApp.ReadModels.DecEventContextAuditEntry
alias MyApp.Events.DecEventContextUserAction
from DecEventContextUserAction, set: [ event_id: "$context.sequenceNumber", occurred_at: :occurred, correlation_id: "$context.correlationId" ]endimport { eventType, IProjectionBuilderFor, IProjectionFor, projection } from '@cratis/chronicle';
@eventType()class DecEventContextUserAction { userId = ''; actionType = '';}
@projection()class DecEventContextAuditTrailProjection implements IProjectionFor<DecEventContextAuditEntry> { define(builder: IProjectionBuilderFor<DecEventContextAuditEntry>): void { builder .autoMap() .from(DecEventContextUserAction, _ => _ .set(m => m.eventId).toEventContextProperty('sequenceNumber') .set(m => m.occurredAt).toEventContextProperty('occurred') .set(m => m.correlationId).toEventContextProperty('correlationId')); }}Read models with context data
Section titled “Read models with context data”Your read models can include properties for event metadata:
public record DecEventContextUserActivity( string UserId, DateTimeOffset LastLogin, DateTimeOffset LastActivity);
public record DecEventContextAuditEntry( ulong EventId, DateTimeOffset OccurredAt, string CorrelationId, string ActionType, string UserId);Kotlin does not support this workflow yet.Java does not support this workflow yet.defmodule MyApp.ReadModels.DecEventContextUserActivity do use Chronicle.ReadModels.ReadModel
defstruct [:user_id, :last_login, :last_activity]end
defmodule MyApp.ReadModels.DecEventContextAuditEntry do use Chronicle.ReadModels.ReadModel
defstruct [:event_id, :occurred_at, :correlation_id, :action_type, :user_id]endclass DecEventContextUserActivity { userId = ''; lastLogin = new Date(); lastActivity = new Date();}
class DecEventContextAuditEntry { eventId: bigint = 0n; occurredAt = new Date(); correlationId = ''; actionType = ''; userId = '';}Composite keys with event context
Section titled “Composite keys with event context”Event context properties can be part of composite keys:
using Cratis.Chronicle.Events;using Cratis.Chronicle.Projections;
[EventType]public record DecEventContextUserActionForKey(string UserId, string ActionType);
public record DecEventContextEventLogKey(DateTimeOffset Date, ulong SequenceNumber);
public record DecEventContextEventLogEntry( DecEventContextEventLogKey Id, string ActionType, string UserId);
public class DecEventContextEventLogProjection : IProjectionFor<DecEventContextEventLogEntry>{ public void Define(IProjectionBuilderFor<DecEventContextEventLogEntry> builder) => builder .From<DecEventContextUserActionForKey>(_ => _ .UsingCompositeKey<DecEventContextEventLogKey>(_ => _ .Set(k => k.Date).ToEventContextProperty(c => c.Occurred) .Set(k => k.SequenceNumber).ToEventContextProperty(c => c.SequenceNumber)) .Set(m => m.ActionType).To(e => e.ActionType) .Set(m => m.UserId).To(e => e.UserId));}Event context in children and joins
Section titled “Event context in children and joins”Event context properties work in child collections and joins:
using Cratis.Chronicle.Events;using Cratis.Chronicle.Projections;
[EventType]public record DecEventContextActivityPerformed(string ActivityId, string ActivityType);
public record DecEventContextActivityLogEntry( string ActivityId, DateTimeOffset Timestamp, ulong SequenceNumber);
public record DecEventContextUserWithActivityLog( IEnumerable<DecEventContextActivityLogEntry> ActivityLog);
public class DecEventContextUserActivityLogProjection : IProjectionFor<DecEventContextUserWithActivityLog>{ public void Define(IProjectionBuilderFor<DecEventContextUserWithActivityLog> builder) => builder .Children(m => m.ActivityLog, children => children .IdentifiedBy(e => e.ActivityId) .AutoMap() .From<DecEventContextActivityPerformed>(_ => _ .UsingKey(e => e.ActivityId) .Set(m => m.Timestamp).ToEventContextProperty(c => c.Occurred) .Set(m => m.SequenceNumber).ToEventContextProperty(c => c.SequenceNumber)));}Event definitions
Section titled “Event definitions”using Cratis.Chronicle.Events;
[EventType]public record DecEventContextUserLoggedIn(string Username);
[EventType]public record DecEventContextUserPerformedAction(string UserId, string ActionType);Kotlin does not support this workflow yet.Java does not support this workflow yet.defmodule MyApp.Events.DecEventContextUserLoggedIn do use Chronicle.Events.EventType, id: "dec-event-context-user-logged-in"
defstruct [:username]end
defmodule MyApp.Events.DecEventContextUserPerformedAction do use Chronicle.Events.EventType, id: "dec-event-context-user-performed-action"
defstruct [:user_id, :action_type]endimport { eventType } from '@cratis/chronicle';
@eventType()class DecEventContextUserLoggedIn { username = '';}
@eventType()class DecEventContextUserPerformedAction { userId = ''; actionType = '';}Common use cases
Section titled “Common use cases”Audit trails
Section titled “Audit trails”Map Occurred, SequenceNumber, and CausedBy for complete audit information.
Debugging and diagnostics
Section titled “Debugging and diagnostics”Include CorrelationId to trace related operations across services.
Time-based queries
Section titled “Time-based queries”Use Occurred for time-series analysis and historical reporting.
Event ordering
Section titled “Event ordering”Use SequenceNumber when you need to preserve exact event ordering.
Source tracking
Section titled “Source tracking”Use EventSourceId to identify which event source produced the event.
Event context properties provide rich metadata that can significantly enhance your read models with timing, traceability, and debugging information.