Skip to content
Browse files

Record user PK as well as username.

Usernames can change, of course, so recording the primary key as well
ensures you can positively identify the user being logged.

The schema is migrated to add the user PK, but I've not included a data
migration to automatically update it on existing log records.
  • Loading branch information...
1 parent c491035 commit a04f5973931ab650d6e39dfb5016c65942f4f17f @fairview committed Nov 9, 2011
Showing with 118 additions and 37 deletions.
  1. +1 −1 peavy/__init__.py
  2. +5 −4 peavy/admin.py
  3. +6 −1 peavy/filters.py
  4. +13 −12 peavy/handlers.py
  5. +45 −0 peavy/migrations/0003_add_user_pk.py
  6. +8 −1 peavy/models.py
  7. +2 −2 peavy/templates/peavy/dashboard.html
  8. +38 −16 peavy/views.py
View
2 peavy/__init__.py
@@ -1,7 +1,7 @@
"""
django-peavy makes it easy to collect and monitor Django application logging.
"""
-VERSION = (0, 7, 2)
+VERSION = (0, 8, 0)
def get_version():
return '.'.join((str(d) for d in VERSION))
View
9 peavy/admin.py
@@ -5,9 +5,9 @@
from peavy.models import LogRecord
class LogRecordAdmin(admin.ModelAdmin):
- list_display = ('timestamp', 'application', 'origin_server', 'client_ip', 'user', 'logger', 'level', 'message')
- list_filter = ('application', 'origin_server', 'user', 'logger', 'level')
- search_fields = ('application', 'origin_server', 'client_ip', 'user', 'logger', 'level', 'message')
+ list_display = ('timestamp', 'application', 'origin_server', 'client_ip', 'username', 'logger', 'level', 'message')
+ list_filter = ('application', 'origin_server', 'username', 'logger', 'level')
+ search_fields = ('application', 'origin_server', 'client_ip', 'username', 'logger', 'level', 'message')
fieldsets = (
(
@@ -25,7 +25,8 @@ class LogRecordAdmin(admin.ModelAdmin):
{
'fields': (
'client_ip',
- 'user',
+ 'user_pk',
+ 'username',
)
}
),
View
7 peavy/filters.py
@@ -11,7 +11,12 @@ def filter(self, record):
request = RequestLoggingMiddleware.context.request
record.uuid = getattr(request, "uuid", "?")
- record.user = getattr(request, "user", "?")
+ if hasattr(request, "user"):
+ record.user_pk = getattr(request.user, 'pk', None)
+ record.username = request.user.username
+ else:
+ record.user_pk = None
+ record.username = "?"
meta = getattr(request, "META", {})
record.client_ip = meta.get("REMOTE_ADDR", "?")
return True
View
25 peavy/handlers.py
@@ -15,11 +15,11 @@ def get_debug_page(self, record, request):
from django.views.debug import ExceptionReporter
- debug_page = ''
+ debug_page = ""
if record.exc_info:
exc_info = record.exc_info
reporter = ExceptionReporter(request, *exc_info)
- debug_page = reporter.get_traceback_html() or ''
+ debug_page = reporter.get_traceback_html() or ""
return debug_page
def get_stack_trace(self, record, request):
@@ -30,11 +30,11 @@ def get_stack_trace(self, record, request):
from django.views.debug import ExceptionReporter
- stack_trace = ''
+ stack_trace = ""
if record.exc_info:
exc_info = record.exc_info
reporter = ExceptionReporter(request, *exc_info)
- stack_trace = '\n'.join(
+ stack_trace = "\n".join(
traceback.format_exception(*record.exc_info)
)
return stack_trace
@@ -52,22 +52,23 @@ def emit(self, record):
self.format(record)
- request = getattr(RequestLoggingMiddleware.context, 'request', None)
+ request = getattr(RequestLoggingMiddleware.context, "request", None)
stack_trace = self.get_stack_trace(record, request)
debug_page = self.get_debug_page(record, request)
from django.conf import settings
- db_name = getattr(settings, 'PEAVY_DATABASE_NAME', 'peavy')
+ db_name = getattr(settings, "PEAVY_DATABASE_NAME", "peavy")
with transaction.commit_on_success(using=db_name):
LogRecord.objects.using(db_name).create(
logger = record.name,
level = record.levelname,
message = record.msg,
- uuid = getattr(record, 'uuid', '?'),
- client_ip = getattr(record, 'client_ip', '?'),
- user = getattr(record, 'user', '?'),
+ uuid = getattr(record, "uuid", "?"),
+ client_ip = getattr(record, "client_ip", "?"),
+ username = getattr(record, "username", "?"),
+ user_pk = getattr(record, "user_pk", None),
stack_trace = stack_trace,
debug_page = debug_page
)
@@ -85,19 +86,19 @@ def emit(self, record):
from django.core.urlresolvers import reverse
from django.contrib.sites.models import Site
- subject = '%s: %s' % (
+ subject = "%s: %s" % (
record.levelname,
record.msg
)
try:
- request = getattr(RequestLoggingMiddleware.context, 'request', None)
+ request = getattr(RequestLoggingMiddleware.context, "request", None)
site = Site.objects.get_current()
request_link = (
"View the log entries for this request:\n\n"
"https://%s%s?request_id=%s\n" % (
site.domain,
- reverse('peavy:dashboard'),
+ reverse("peavy:dashboard"),
record.uuid
)
)
View
45 peavy/migrations/0003_add_user_pk.py
@@ -0,0 +1,45 @@
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+
+ # Adding field 'LogRecord.user_pk'
+ db.add_column('peavy_logrecord', 'user_pk', self.gf('django.db.models.fields.IntegerField')(db_index=True, null=True, blank=True), keep_default=False)
+
+ # rename user to username
+ db.rename_column('peavy_logrecord', 'user', 'username')
+
+
+ def backwards(self, orm):
+
+ # Deleting field 'LogRecord.user_pk'
+ db.delete_column('peavy_logrecord', 'user_pk')
+
+ # rename username back to user
+ db.rename_column('peavy_logrecord', 'username', 'user')
+
+ models = {
+ 'peavy.logrecord': {
+ 'Meta': {'ordering': "('-timestamp',)", 'object_name': 'LogRecord'},
+ 'application': ('django.db.models.fields.CharField', [], {'default': "'sandbox'", 'max_length': '256', 'db_index': 'True'}),
+ 'client_ip': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '128', 'blank': 'True'}),
+ 'debug_page': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'level': ('django.db.models.fields.CharField', [], {'max_length': '32', 'db_index': 'True'}),
+ 'logger': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'db_index': 'True'}),
+ 'message': ('django.db.models.fields.TextField', [], {'db_index': 'True'}),
+ 'origin_server': ('django.db.models.fields.CharField', [], {'default': "'kaze.jkcl.local'", 'max_length': '256', 'db_index': 'True'}),
+ 'stack_trace': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'timestamp': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'db_index': 'True'}),
+ 'user': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '256', 'blank': 'True'}),
+ 'user_pk': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+ 'uuid': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '256', 'blank': 'True'})
+ }
+ }
+
+ complete_apps = ['peavy']
View
9 peavy/models.py
@@ -40,7 +40,14 @@ class LogRecord(models.Model):
db_index = True
)
- user = models.CharField(
+ user_pk = models.IntegerField(
+ blank=True,
+ null=True,
+ db_index=True,
+ help_text = _("The primary key of the user making the request in which this record was logged."),
+ )
+
+ username = models.CharField(
max_length = 256,
help_text = _("The username of the user making the request in which this record was logged."),
blank = True,
View
4 peavy/templates/peavy/dashboard.html
@@ -73,8 +73,8 @@
</div>
<div class="user">
<a
- title="Click to filter on user {{record.user}}"
- href="{{request.path}}{% query_string username=record.user page= %}">{{record.user}}</a>
+ title="Click to filter on user {{record.user_pk}}{% if record.username %} ({{record.username}}){% endif %}"
+ href="{{request.path}}{% query_string user_pk=record.user_pk username=record.username page= %}">{{record.user_pk}}{% if record.username %} ({{record.username}}){% endif %}</a>
</div>
<div class="request_id request_id-{{record.uuid}}" data-request-id="{{record.uuid}}">
<a
View
54 peavy/views.py
@@ -12,43 +12,65 @@
from peavy.models import LogRecord
-@permission_required('peavy.view_logs')
+@permission_required("peavy.view_logs")
def dashboard(request):
"""
The main view: all the logs, with filters and pagination.
"""
records = LogRecord.objects.all()
- applications = request.GET.getlist('application')
+ applications = request.GET.getlist("application")
if applications:
records = records.filter(application__in=applications)
- client_ips = request.GET.getlist('client_ip')
+ client_ips = request.GET.getlist("client_ip")
if client_ips:
records = records.filter(client_ip__in=client_ips)
- levels = request.GET.getlist('level')
+ levels = request.GET.getlist("level")
if levels:
records = records.filter(level__in=levels)
- loggers = request.GET.getlist('logger')
+ loggers = request.GET.getlist("logger")
if loggers:
records = records.filter(logger__in=loggers)
- origin_servers = request.GET.getlist('origin_server')
+ origin_servers = request.GET.getlist("origin_server")
if origin_servers:
records = records.filter(origin_server__in=origin_servers)
- request_ids = request.GET.getlist('request_id')
+ request_ids = request.GET.getlist("request_id")
if request_ids:
records = records.filter(uuid__in=request_ids)
- users = request.GET.getlist('username')
- if users:
- records = records.filter(user__in=users)
+ show_anonymous_users = False
+ user_pks = []
+ for pk in request.GET.getlist("user_pk"):
+ if pk == "None":
+ show_anonymous_users = True
+ else:
+ user_pks.append(pk)
- message_filters = request.GET.getlist('message')
+ user_pk_filter = None
+
+ if show_anonymous_users:
+ user_pk_filter = Q(user_pk__isnull=True)
+
+ if user_pks:
+ if not user_pk_filter:
+ user_pk_filter = Q(user_pk__in=user_pks)
+ else:
+ user_pk_filter |= Q(user_pk__in=user_pks)
+
+ if user_pk_filter:
+ records = records.filter(user_pk_filter)
+
+ usernames = request.GET.getlist("username")
+ if usernames:
+ records = records.filter(username__in=usernames)
+
+ message_filters = request.GET.getlist("message")
if message_filters:
message_query = None
for term in message_filters:
@@ -61,16 +83,16 @@ def dashboard(request):
if message_query is not None:
records = records.filter(message_query)
- page_number = int(request.GET.get('page', 1))
- count = int(request.GET.get('count', 20))
+ page_number = int(request.GET.get("page", 1))
+ count = int(request.GET.get("count", 20))
paginator = Paginator(object_list=records, per_page=count, allow_empty_first_page=True)
if page_number < 1:
- redirect = re.sub('page=\d+', 'page=%s' % paginator.num_pages, request.get_full_path())
+ redirect = re.sub("page=\d+", "page=%s" % paginator.num_pages, request.get_full_path())
return http.HttpResponseRedirect(redirect)
if page_number > paginator.num_pages:
- redirect = re.sub('page=\d+', 'page=1', request.get_full_path())
+ redirect = re.sub("page=\d+", "page=1", request.get_full_path())
return http.HttpResponseRedirect(redirect)
records = paginator.page(page_number)
@@ -80,7 +102,7 @@ def dashboard(request):
}
return render_to_response(
- 'peavy/dashboard.html',
+ "peavy/dashboard.html",
data,
context_instance = RequestContext(request)
)

0 comments on commit a04f597

Please sign in to comment.
Something went wrong with that request. Please try again.