Shout-out to eventlog

30 October 2014   4 comments   Django

Mind That Age!

This blog post is 4 years old! Most likely, its content is outdated. Especially if it's technical.

Powered by Fusion×

If you do things with the Django ORM and want an audit trails of all changes you have two options:

  1. Insert some cleverness into a pre_save signal that writes down all changes some way.

  2. Use eventlog and manually log things in your views.

(you have other options too but I'm trying to make a point here)

eventlog is almost embarrassingly simple. It's basically just a model with three fields:

You use it like this:

from eventlog.models import log

def someview(request):
    if request.method == 'POST':
        form = SomeModelForm(request.POST)
        if form.is_valid():
            new_thing =
            log(request.user, 'mymodel.create', {
                # You can put anything JSON 
                # compatible in here
            return redirect('someotherview')
        form = SomeModelForm()
    return render(request, 'view.html', {'form': form})

That's all it does. You then have to do something with it. Suppose you have an admin page that only privileged users can see. You can make a simple table/dashboard with these like this:

from eventlog.models import Log  # Log the model, not log the function

def all_events(request):
    all = Log.objects.all()
    return render(request, 'all_events.html', {'all': all})

And something like this to to all_events.html:

  {% for event in all %}
    <td>{{ event.user.username }}</td>
    <td>{{ event.timestamp | date:"D d M Y" }}</td>
    <td>{{ event.action }}</td>
    <td>{{ event.extra }}</td>
  {% endfor %}

What I like about it is that it's very deliberate. By putting it into views at very specific points you're making it an audit log of actions, not of data changes.

Projects with overly complex model save signals tend to dig themselves into holes that make things slow and complicated. And it's not unrealistic that you'll then record events that aren't particularly important to review. For example, a cron job that increments a little value or something. It's more interesting to see what humans have done.

I just wanted to thank the Eldarion guys for eventlog. It's beautifully simple and works perfectly for me.


Greg Taylor
We started with something like this, but ended up not liking the DB bloat that this sort of thing causes. We also started finding that we were using our event log data for some light analytics, which isn't something we had anticipated.

After pondering a number of alternative methods (breaking the event log out into its own DB was the leading candidate), we discovered You throw event logs at it and you can do all kinds of filtering/graphing/statistical calculations based on the key/value pairs within each body.

I don't work for, but we really love it at Pathwright. Avoids a lot of unnecessary DB writes and DB bloat, plus our less technical business staff can still figure out how to query it without involving a developer.
Peter Bengtsson looks awesome! I just spent a coupla' minutes skimming their docs and stuff.

However, even though it uses a "persistent connection" it's still a HTTPS POST over the network every time it needs to send something. Blocking too. Perhaps it's doable to "up" that to be a gevent greenlet or something so it can send async but that's probably not trivial.

As far as bloat is concerned, I think this is where it matters. I use my eventlog only to send events when users do something that relates to changing the state (e.g. doing a POST) so there aren't that many events actually.
with postgres you could do this entirely inside the db server. See for example sql. No code in django needed at all
Peter Bengtsson
But then you'd get every insert or update or something, right?

That's no explicit and not very deliberate.
Thank you for posting a comment

Your email will never ever be published

Related posts

Go vs. Python 24 October 2014
uwsgi and uid 03 November 2014
Related by Keyword:
How do log ALL PostgreSQL SQL happening 20 July 2015
Javascript tip: nifty use of the console.log function in Firebug 07 November 2010
Related by Text:
How to "onchange" in ReactJS 21 October 2015
How to use django-cache-memoize 03 November 2017
Really simple Django view function timer decorator 08 December 2017
Public Class Fields saves sooo many keystrokes in React code 14 April 2017
Custom CacheMiddleware that tells Javascript a page is cached in Django 24 August 2009