Koherent is a python library that allows you to integrated based audit logging into your application. It thinly wraps the django-simple-history library, and provides a simple interface for logging and reverting changes to your models.
Note: This library is still heavily tied to the Arkitekt Framework. We are working on making it more generic.
By default (soon to be configurable), we track the following parameters:
user
- The user who made the changeapp
- The application that made the change (if present)assignation_id
- In which context the change was made (if present)action
- The action that was performed (create, update, delete)model
- The model that was changed
An assignation ID (or more commonly known as a context_id
or correlation_id
) is a unique identifier that is used to group
changes together. FOr example, if you have a Task
model, and you want to track all changes to a specific task, you would
use the Task
's ID as the assignation ID. This allows you to easily track all changes to a specific task, and revert them
if necessary.
Koherent is a Django Libary, so you will have to add it to your INSTALLED_APPS
in your settings.py
file.
INSTALLED_APPS = [
...
'koherent',
...
]
Then in your models, you will need to add the KoherentHistoryModel
mixin to your model.
from koherent.fields import HistoryField, HistoricForeignKey
import koherent.signal # This is required to register the signal handlers
class MyModel(KoherentHistoryModel):
your_field = models.CharField(max_length=255)
history = HistoryField()
...
Koherent is designed to work with Strawberry, so you will need to add its extension to your schema.
import strawberry_django
from koherent.strawberry.extension import KoherentExtension
from app import models
@strawberry_django.type(models.MyModel)
class MyModel:
id: strawberry.ID
name: str
@strawberry.type
class Query:
@strawberry_django.field
def create_model(self, info, your_field: str) -> MyModel:
model = models.MyModel.objects.create(your_field=your_field)
# This will create a new history entry (by sending a signal)
# bound to the current user and the assignation id
return model
@strawberry_django.field
def update_model(self, info, id: strawberry.ID, your_field: str) -> MyModel:
model = models.MyModel.objects.get(id=id)
model.your_field = your_field
model.save()
# This will create a new history entry (by sending a signal)
# bound to the current user and the assignation id
return model
schema = strawberry.Schema(query=Query, extensions=[KoherentExtension])
Currently we require that you use the Kante
GraphQL library, as it provides the assignation_id
and user
context
required for the audit logging. We are soon going to make this more generic.
In the Arkitekt Framework, we use the assignation_id
to track changes that are done by an app when a user is calling that
app through an Arkitekt Rekuest. This allows us to track all changes that are done by a specific Rekuest, and revert them
if necessary.
from arkitekt import register
from service.generated_api import create_model, update_model, delete_model, MyModel
@register
def do_some_transactions(name: str) -> MyModel:
""" Do some transactions """
# Within this function, all api requests will have the assignatio-id header
# set to the same value. This allows us to track all changes that are done
z = create_model(name=name)
f = update_model(id=z.id, name="New Name") # tracked with the same assignation_id
return f