novastats and other site templates

This commit is contained in:
Sandy Walsh 2012-02-29 07:46:37 -06:00
parent b08ccb6fbd
commit 2147038a27
5 changed files with 42 additions and 35 deletions

View File

@ -20,6 +20,8 @@ from django.db import models
class Tenant(models.Model): class Tenant(models.Model):
email = models.CharField(max_length=50) email = models.CharField(max_length=50)
project_name = models.CharField(max_length=50) project_name = models.CharField(max_length=50)
nova_stats_template = models.CharField(max_length=200)
loggly_template = models.CharField(max_length=200)
tenant_id = models.AutoField(primary_key=True, unique=True) tenant_id = models.AutoField(primary_key=True, unique=True)
@ -35,13 +37,13 @@ class RawData(models.Model):
blank=True, db_index=True) blank=True, db_index=True)
when = models.DateTimeField(db_index=True) when = models.DateTimeField(db_index=True)
microseconds = models.IntegerField(default=0) microseconds = models.IntegerField(default=0)
publisher = models.CharField(max_length=50, null=True, publisher = models.CharField(max_length=100, null=True,
blank=True, db_index=True) blank=True, db_index=True)
event = models.CharField(max_length=50, null=True, event = models.CharField(max_length=50, null=True,
blank=True, db_index=True) blank=True, db_index=True)
service = models.CharField(max_length=50, null=True, service = models.CharField(max_length=50, null=True,
blank=True, db_index=True) blank=True, db_index=True)
host = models.CharField(max_length=50, null=True, host = models.CharField(max_length=100, null=True,
blank=True, db_index=True) blank=True, db_index=True)
instance = models.CharField(max_length=50, null=True, instance = models.CharField(max_length=50, null=True,
blank=True, db_index=True) blank=True, db_index=True)
@ -50,4 +52,4 @@ class RawData(models.Model):
class TenantForm(forms.ModelForm): class TenantForm(forms.ModelForm):
class Meta: class Meta:
model = Tenant model = Tenant
fields = ('email', 'project_name') fields = ('email', 'project_name', 'nova_stats_template', 'loggly_template')

View File

@ -83,13 +83,22 @@ def _parse(tenant, args, json_args):
return {} return {}
def _post_process_raw_data(rows, highlight=None): def _post_process_raw_data(rows, state, highlight=None):
for row in rows: for row in rows:
if "error" in row.routing_key: if "error" in row.routing_key:
row.is_error = True row.is_error = True
if highlight and row.id == int(highlight): if highlight and row.id == int(highlight):
row.highlight = True row.highlight = True
row.when += datetime.timedelta(microseconds=row.microseconds) row.when += datetime.timedelta(microseconds=row.microseconds)
novastats = state.tenant.nova_stats_template
if novastats and row.instance:
novastats = novastats.replace("[instance]", row.instance)
row.novastats = novastats
loggly = state.tenant.loggly_template
if loggly and row.instance:
loggly = loggly.replace("[instance]", row.instance)
row.loggly = loggly
class State(object): class State(object):
def __init__(self): def __init__(self):
@ -203,12 +212,13 @@ def details(request, tenant_id, column, row_id):
if column != 'when': if column != 'when':
rows = rows.filter(**{column:value}) rows = rows.filter(**{column:value})
else: else:
value += datetime.timedelta(microseconds=row.microseconds)
from_time = value - datetime.timedelta(minutes=1) from_time = value - datetime.timedelta(minutes=1)
to_time = value + datetime.timedelta(minutes=1) to_time = value + datetime.timedelta(minutes=1)
rows = rows.filter(when__range=(from_time, to_time)) rows = rows.filter(when__range=(from_time, to_time))
rows = rows.order_by('-when', '-microseconds')[:200] rows = rows.order_by('-when', '-microseconds')[:200]
_post_process_raw_data(rows, highlight=row_id) _post_process_raw_data(rows, state, highlight=row_id)
c['rows'] = rows c['rows'] = rows
c['allow_expansion'] = True c['allow_expansion'] = True
c['show_absolute_time'] = True c['show_absolute_time'] = True
@ -231,21 +241,25 @@ def host_status(request, tenant_id):
state = _get_state(request, tenant_id) state = _get_state(request, tenant_id)
c = _default_context(state) c = _default_context(state)
hosts = models.RawData.objects.filter(tenant=tenant_id).\ hosts = models.RawData.objects.filter(tenant=tenant_id).\
filter(host__gt='').\
order_by('-when', '-microseconds')[:20] order_by('-when', '-microseconds')[:20]
_post_process_raw_data(hosts) _post_process_raw_data(hosts, state)
c['rows'] = hosts c['rows'] = hosts
return render_to_response('host_status.html', c) return render_to_response('host_status.html', c)
@tenant_check @tenant_check
def instance_status(request, tenant_id): def search(request, tenant_id):
state = _get_state(request, tenant_id) state = _get_state(request, tenant_id)
c = _default_context(state) c = _default_context(state)
instances = models.RawData.objects.filter(tenant=tenant_id).\ column = request.POST.get('field', None)
exclude(instance='n/a').\ value = request.POST.get('value', None)
exclude(instance__isnull=True).\ rows = None
order_by('-when', '-microseconds')[:20] if column != None and value != None:
_post_process_raw_data(instances) rows = models.RawData.objects.filter(tenant=tenant_id).\
c['rows'] = instances filter(**{column:value}).\
return render_to_response('instance_status.html', c) order_by('-when', '-microseconds')[:200]
_post_process_raw_data(rows, state)
c['rows'] = rows
c['allow_expansion'] = True
c['show_absolute_time'] = True
return render_to_response('rows.html', c)

View File

@ -28,8 +28,8 @@
{% endblock %} {% endblock %}
{% block body %} {% block body %}
<div style='float:right;'>{{state.tenant.email}} (TID:{{state.tenant.tenant_id}}) - {{state.tenant.project_name}} <a href='/logout'>logout</a></div> <div style='float:right;'><a href='/logout'>logout</a></div>
<div class='status-title'>Recent Activity</div> <div class='status-title'>Recent Activity - {{state.tenant.project_name}} (TID:{{state.tenant.tenant_id}})</div>
<div id='host-box' class='status std-height'> <div id='host-box' class='status std-height'>
<div id='host_activity' class='status-inner'> <div id='host_activity' class='status-inner'>
{% include "host_status.html" %} {% include "host_status.html" %}

View File

@ -34,11 +34,13 @@
<td class='cell-border'><a href='#' onclick='details({{state.tenant.tenant_id}}, "host", {{row.id}});'>{{row.host}}</a></td> <td class='cell-border'><a href='#' onclick='details({{state.tenant.tenant_id}}, "host", {{row.id}});'>{{row.host}}</a></td>
<td class='cell-border'><b><a href='#' onclick='details({{state.tenant.tenant_id}}, "event", {{row.id}});'>{{row.event}}</a></b></td> <td class='cell-border'><b><a href='#' onclick='details({{state.tenant.tenant_id}}, "event", {{row.id}});'>{{row.event}}</a></b></td>
<td class='cell-border'> <td class='cell-border'>
<a href='#' onclick='details({{state.tenant.tenant_id}}, "instance", {{row.id}});'>
{% if row.instance %} {% if row.instance %}
<a href='{{row.loggly}}' target="_blank">(L)</a>
<a href='{{row.novastats}}' target="_blank">(S)</a>
<a href='#' onclick='details({{state.tenant.tenant_id}}, "instance", {{row.id}});'>
{{row.instance}} {{row.instance}}
{% endif %}
</a> </a>
{% endif %}
</td> </td>
<td class='cell-border'><a href='#' onclick='details({{state.tenant.tenant_id}}, "when", {{row.id}});'>{% if show_absolute_time %}{{row.when}} (+{{row.when.microsecond}}){%else%}{{row.when|timesince:utc}} ago{%endif%}</a></td> <td class='cell-border'><a href='#' onclick='details({{state.tenant.tenant_id}}, "when", {{row.id}});'>{% if show_absolute_time %}{{row.when}} (+{{row.when.microsecond}}){%else%}{{row.when|timesince:utc}} ago{%endif%}</a></td>
</tr> </tr>

21
urls.py
View File

@ -1,20 +1,9 @@
from django.conf.urls.defaults import patterns, include, url from django.conf.urls.defaults import patterns, include, url
# Uncomment the next two lines to enable the admin:
# from django.contrib import admin
# admin.autodiscover()
urlpatterns = patterns('', urlpatterns = patterns('',
url(r'^$', 'stacktach.views.welcome', name='welcome'), url(r'^', include('stacktach.url')),
url(r'new_tenant', 'stacktach.views.new_tenant', name='new_tenant'),
url(r'logout', 'stacktach.views.logout', name='logout'),
url(r'^(?P<tenant_id>\d+)/$', 'stacktach.views.home', name='home'),
url(r'^(?P<tenant_id>\d+)/data/$', 'stacktach.views.data',
name='data'),
url(r'^(?P<tenant_id>\d+)/details/(?P<column>\w+)/(?P<row_id>\d+)/$',
'stacktach.views.details', name='details'),
url(r'^(?P<tenant_id>\d+)/search/$',
'stacktach.views.search', name='search'),
url(r'^(?P<tenant_id>\d+)/expand/(?P<row_id>\d+)/$',
'stacktach.views.expand', name='expand'),
url(r'^(?P<tenant_id>\d+)/host_status/$',
'stacktach.views.host_status', name='host_status'),
url(r'^(?P<tenant_id>\d+)/instance_status/$',
'stacktach.views.instance_status', name='instance_status'),
) )