Skip to content

Commit 1f30bb4

Browse files
committed
final version with file log and cron-ready management function
1 parent 968d666 commit 1f30bb4

File tree

9 files changed

+97
-10
lines changed

9 files changed

+97
-10
lines changed

apps/pinger/forms.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,6 @@ def clean_file(self):
2929
'''
3030
_file = self.cleaned_data["file"]
3131
for (num, line) in enumerate(_file):
32-
if len(line.split('|')) < 2:
32+
if len(line.split('|')) < 2 or len(line.split('|')) > 3:
3333
raise forms.ValidationError("Invalid file format in line %d: %s" % (num+1, line))
3434
return _file

apps/pinger/management/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
__author__ = 'ubuntu'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
__author__ = 'ubuntu'
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from django.core.management.base import BaseCommand, CommandError
2+
from apps.pinger.ping import SendPing
3+
4+
class Command(BaseCommand):
5+
'''
6+
Manage script to run with cron
7+
for corn to work with venv, cd to project, choose right pyhon, eun command
8+
cd /home/my/project && /home/my/virtual/bin/python /home/my/project/manage.py pinger > /var/log/pinger_cron.log 2>&1
9+
'''
10+
help = 'Checks urls added to database. intended to use with cron'
11+
12+
def handle(self, *args, **options):
13+
14+
pinger = SendPing()
15+
try:
16+
pinger.run()
17+
except Exception, e:
18+
raise CommandError('Exception caught: %s, %s' % (e.__doc__, e.message))
19+
20+
self.stdout.write('Successfully run pinger!')

apps/pinger/models.py

+18-4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
from django.core.urlresolvers import reverse
33
from django.db import models
44
from datetime import datetime as dt
5+
from django.utils.timezone import utc
6+
from settings.common import LOGFILE
7+
58

69
class BaseModel(models.Model):
710
'''
@@ -47,7 +50,7 @@ class PingHistory(BaseModel):
4750
haystack = models.ForeignKey('Haystack')
4851
http_code=models.IntegerField(default=0)
4952
time_ms = models.IntegerField(default=0)
50-
phrase_found = models.BooleanField(default=False)
53+
phrase_found = models.BooleanField(default=True)
5154

5255
@property
5356
def is_error(self):
@@ -61,7 +64,18 @@ def save(self, *args, **kwargs):
6164
self.haystack.last_time_ms = self.time_ms
6265
self.haystack.last_checked = self.created
6366
if not self.is_error:
64-
self.haystack.last_ok = dt.utcnow()
67+
self.haystack.last_ok = dt.utcnow().replace(tzinfo=utc)
6568
else:
66-
self.haystack.last_error = dt.utcnow()
67-
self.haystack.save()
69+
self.haystack.last_error = dt.utcnow().replace(tzinfo=utc)
70+
self.haystack.save()
71+
72+
#append to log file
73+
line = '[{status}] {url} @ {check_time}: got {code} response in {ms}ms and requirement {phrase_found}\n'.format(
74+
status='FAILED' if self.is_error else 'SUCCESS',
75+
url=self.haystack.url,
76+
check_time=self.created,
77+
code=self.http_code,
78+
ms=self.time_ms,
79+
phrase_found='FAILED' if not self.phrase_found else 'SUCCESS' )
80+
with open(LOGFILE, 'a+') as f:
81+
f.write(line)

apps/pinger/ping.py

+10-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
# -*- coding: utf-8 -*-
2+
import logging
23
import urllib2
34
from apps.pinger.models import Haystack, PingHistory
45

6+
logger = logging.getLogger('pinger')
7+
58

69
class SendPing(object):
710
CHUNK = 16 * 1024
@@ -33,26 +36,30 @@ def check_phrase(self, phrase, urldata):
3336

3437
def ping_straw(self, straw):
3538
import time
36-
error = False
39+
error = True
3740
code = 0
3841

3942
tstart = time.time()
4043

4144
try:
4245
url_data, code = self.stream_data_from_url(straw.url)
46+
logger.debug('url data: %s' % url_data)
47+
error=False
4348
except:
4449
error = True
4550

4651
tend = time.time()
4752
ms = tend-tstart
4853

4954
if not error:
50-
error = self.check_phrase(straw.search_phrase, url_data)
55+
check_result = self.check_phrase(straw.search_phrase, url_data)
56+
else:
57+
check_result=False
5158

5259
ping = PingHistory(
5360
haystack=straw,
5461
time_ms=ms,
55-
phrase_found=error,
62+
phrase_found=check_result,
5663
http_code=code,
5764
)
5865
ping.save()

apps/pinger/urls.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# -*- coding: utf-8 -*-
22
from django.conf.urls import patterns, url
3-
from apps.pinger.views import HaystackUploadView, HaystackCreateView, HaystackListView, HaystackUpdateView, HaystackDeleteView, HaystackRunView
3+
from apps.pinger.views import HaystackUploadView, HaystackCreateView, HaystackListView, HaystackUpdateView, HaystackDeleteView, HaystackRunView, HaystackLogView
44

55
urlpatterns = patterns('',
66
url(r'upload/$', HaystackUploadView.as_view(), name='hay_upload'),
@@ -9,6 +9,7 @@
99
url(r'list/(?P<pk>\d+)/$', HaystackUpdateView.as_view(), name='hay_update'),
1010
url(r'list/(?P<pk>\d+)/delete/$', HaystackDeleteView.as_view(), name='hay_delete'),
1111
url(r'run/$', HaystackRunView.as_view(), name='hay_run'),
12+
url(r'log/(?P<num>\d+)/$$', HaystackLogView.as_view(), name='hay_log'),
1213

1314
url(r'$', HaystackListView.as_view(), name='home'),
1415
)

apps/pinger/views.py

+23-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
# -*- coding: utf-8 -*-
2-
from django.http import HttpResponseRedirect
2+
from django.http import HttpResponseRedirect, HttpResponse
33
from django.views.generic import CreateView, ListView, UpdateView, DeleteView
44
from django.views.generic.base import TemplateResponseMixin, ContextMixin, View
55
from apps.pinger.forms import UploadFileForm, HaystackCreateModelForm
66
from apps.pinger.models import Haystack
77
from django.core.urlresolvers import reverse_lazy
88
from apps.util.mixins import MessageMixin
9+
from settings.common import LOGFILE
10+
911

1012
class HaystackUploadView(TemplateResponseMixin, ContextMixin, View):
1113
form_class = UploadFileForm
@@ -40,26 +42,31 @@ def line_to_haystack(self, line):
4042
)
4143
straw.save()
4244

45+
4346
class HaystackListView(ListView):
4447
model = Haystack
4548

49+
4650
class HaystackCreateView(MessageMixin, CreateView):
4751
model = Haystack
4852
form_class = HaystackCreateModelForm
4953
success_message='Added new item!'
5054
success_url = reverse_lazy('hay_list')
5155

56+
5257
class HaystackUpdateView(MessageMixin, UpdateView):
5358
model = Haystack
5459
form_class = HaystackCreateModelForm
5560
success_message='Data was successfully edited'
5661
success_url = reverse_lazy('hay_list')
5762

63+
5864
class HaystackDeleteView(MessageMixin, DeleteView):
5965
model = Haystack
6066
success_message='Link was removed from monitoring system.'
6167
success_url = reverse_lazy('hay_list')
6268

69+
6370
class HaystackRunView(View):
6471
success_url = reverse_lazy('hay_list')
6572

@@ -69,3 +76,18 @@ def get(self, request, *args, **kwargs):
6976
pinger.run()
7077
return HttpResponseRedirect(self.success_url)
7178

79+
80+
class HaystackLogView(View):
81+
82+
def get(self, request, *args, **kwargs):
83+
num = int(kwargs.pop('num') or 5)
84+
85+
from apps.util.util import tail
86+
87+
with open(LOGFILE, 'r') as f:
88+
data, more = tail(f, num)
89+
if more:
90+
data = 'Showing last %d lines. Full og file avialbale at: %s\n\n%s' % (num, LOGFILE, data)
91+
response = HttpResponse(data, content_type='text/plain')
92+
93+
return response

apps/util/util.py

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
def tail(f, n, offset=None):
2+
"""Reads a n lines from f with an offset of offset lines. The return
3+
value is a tuple in the form ``(lines, has_more)`` where `has_more` is
4+
an indicator that is `True` if there are more lines in the file.
5+
"""
6+
avg_line_length = 74
7+
to_read = n + (offset or 0)
8+
9+
while 1:
10+
try:
11+
f.seek(-(avg_line_length * to_read), 2)
12+
except IOError:
13+
# apparently file is smaller than what we want
14+
# to step back, go to the beginning instead
15+
f.seek(0)
16+
pos = f.tell()
17+
lines = f.read().splitlines()
18+
if len(lines) >= to_read or pos == 0:
19+
return '\n'.join(lines[-to_read:offset and -offset or None]), \
20+
len(lines) > to_read or pos > 0
21+
avg_line_length *= 1.3

0 commit comments

Comments
 (0)