Audit Trail and Event Sourcing in Chiron

Chiron, Yields.io enterprise platform for model risk management, is introducing an audit trail as a new feature. This article will explain this feature and its benefits, as well as how we manage to do it using event sourcing.

An audit trail is a sequence of changes in a system. It allows traceability and reconstruction of the historic state of a system (up to the current state):

  • traceability allows examination of what has occurred, when, and by whom.
  • reproducibility allows us to replay past changes to arrive at the same final state.

Because of the aforementioned properties, audit trail data should never be altered. This guarantees proof of what happened in the system. In contrast, many existing systems keep only the current state of the data, where past changes are lost when deleted or overwritten by new data.

Audit trails are implemented in many real-life applications: voting ballots, bank transactions, a captain’s journal. In IT, it’s usually achieved by appending to a file. This allows to read a history of changes, but is not easy to use it otherwise.

Events as a source of truth

Using events is our preferred way of achieving an audit trail functionality.

An event is a description of what has happened. Events are stored in an append-only journal, they can only be added, never modified or deleted. A single event does not contain the entire state of the data, only a partial encapsulating the modifications. To obtain the current state, all events are replayed from the journal.

This technique is referred to as event sourcing – events are the source of truth in the system. We can query the events’ history to obtain the state of the data, or we can propagate them to notify other parts of the system about the change.

This is a stark contrast to a system in which only the current state is available, likely stored in classical RDBMS or NoSQL. Event journal can itself be stored in a relational database or in any other type of data storage as long as it is used in an append-only manner.

Example of events

To better understand events, let’s use the example of an online shop, where a user can add and remove items to and from their cart.

Without event sourcing

In a system without events, when the user is ready to order, the data in the cart is submitted:

    Cart(
        items=(Item(id=100, quantity=3),
            Item(id=101, quantity=2)),
        userId=23
    )

We now know what the user wants to buy: the quantities of two products. Details of the users interactions are lacking, the user might have performed certain actions before submitting the final content of their cart.

With event sourcing

In a system with events, user actions are stored as events, our cart might look like:

  • ItemAdded(time=9:30:29, transactionId=23, id=100, quantity=4)
  • ItemAdded(time=9:31:45, transactionId=23, id=100, quantity=2)
  • ItemAdded(time=9:32:49, transactionId=23, id=101, quantity=1)
  • ItemAdded(time=9:33:55, usetransactionIdrId=23, id=101, quantity=1)
  • ItemRemoved(time=9:34:34, transactionId=23, id=102, quantity=3)
  • CartSubmitted(time=9:36:34, transactionId=23, userId=42)

The resulting cart is the same, but we obtain much more useful information.

For example, a user added 4 items with id=100 before removing 2 of them. Maybe the price was too high? Maybe the description was confusing? If it happens more for this particular product than for others, we may want to investigate why.

We can also infer that the user spent approximately 6 minutes interacting with the site prior to submitting their order. This enables us to mine that information by analysing the events, for example:

  • average time the user spent interacting with the site
  • clusters of products that were added and removed together

This is a simple example, but it highlights the potential of events for data mining and analysis, in addition to an audit trail.

Domain-driven development and command-query responsibility separation

In addition to event sourcing, there exist two more techniques that are complementary to having an audit trail.

DDD is a modelling technique that complements event-based systems. Concepts such as bounded contexts and aggregates help to organise events into logical groups. As such, events are grouped and replayed only for a specific entity – no need to replay all the events, just those that correspond to a given object.

CQRS is another modelling technique that further organises the system into two modules:

  • commands are translated into events
  • events are stored and used to create projections for simplified querying of the data

Events in Chiron

Events are the single source of truth in Chiron. The current state of the platform is calculated as a function of past events. For example, a Data Set can have the following events emitted (here, from the newest to the oldest):

Events in Chiron - overview

Users can examine each event that modified the Data Set’s state, for example:

Events in Chiron - per event

This gives users a detailed insight into the evolution of their data inside Chiron.

In summary

The core benefits of an audit trail implemented with event sourcing:

  • auditing of an internal system. Who and when modified the data?
  • navigating the timeline of the system. We can generate the same state of a system at any given time, by replaying all events starting at the beginning of the event journal.
  • debugging issues. It’s easier to understand a problem when we have a finely grained view on the history of a system.

Users of Chiron can use the audit trail with events feature in the 15.2 release for Models and Data Sets; Data Model Mappings, Stages and Sessions in the upcoming 16.0 release.

Interested in learning more? Watch a demo of Chiron, our flagship product.