Example #1
0
            if not series:
                self.log.info('skipping dataset due to lack of series')
                continue
            d = interval_map[min(s.interval for s in series)]

            self.log.info('ds.name = %s' % (ds.name,))
            if ds.name in ('load1', 'load5', 'load15', 'cpu_count'):
                d['load'][ds.name] = ds.encode()
            elif ds.name.startswith('cpu_'):
                _, suffix = ds.name.split('_', 1)
                if suffix in ('total', 'user', 'system', 'nice', 'iowait'):
                    d['cpu'][suffix] = ds.encode()
            elif ds.name.startswith('mem_'):
                _, suffix = ds.name.split('_', 1)
                if suffix in ('total', 'buffers', 'cached', 'resident', 'used'):
                    d['memory'][suffix] = ds.encode()

        for k, v in interval_map.iteritems():
            if not dict(v):
                continue
            r = {'key': self.key, 'interval': int(k / 2.0), 'datasets': {}}
            for k, v in v.iteritems():
                r['datasets'][k] = v
            result.append(r)

        s = simplejson.dumps(result, sort_keys=True, indent=2)
        self.response.headers['Content-Type'] = 'text/plain'
        self.response.out.write(s + '\n')

add_route(CollectorTemplate, '/api/collector.json')
Example #2
0
from lexigraph.view import add_route
from lexigraph.handler import InteractiveHandler

class Home(InteractiveHandler):

    def get(self):
        if self.request.path != '/':
            self.redirect('/')
            return
        self.env['use_ssl'] = False
        self.render_template('home.html')

add_route(Home, '/')
Example #3
0
        # simple and fast code if only one dataset
        if len(self.datasets) == 1:
            dataset = self.datasets[0]
            self.response.out.write('Timestamp,%s\n' % (dataset.name,))
            points = self.get_points_for_dataset(dataset)
            for p in points:
                self.response.out.write('%s,%s\n' % (p.timestamp.strftime('%s'), p.value))
        else:
            header = ['Timestamp'] + [ds.name for ds in self.datasets]
            self.response.out.write(','.join(header) + '\n')
            points = []
            for ds in self.datasets:
                points.append(self.get_points_for_dataset(ds))

            times = defaultdict(dict)
            dataset_names = [ds.name for ds in self.datasets]
            for name, point_list in zip(dataset_names, points):
                for p in point_list:
                    time = config.graph_resolution * (int(p.timestamp.strftime('%s')) / config.graph_resolution)
                    times[time][name] = p.value

            for t in sorted(times.keys()):
                vals = times[t]
                self.log.info('vals = %s' % (vals,))
                output = [t]
                for name in dataset_names:
                    output.append(vals.get(name, ''))
                self.response.out.write(','.join(str(x) for x in output) + '\n')

add_route(CSV, '/api/csv')
Example #4
0
    requires_login = True

    def post(self):
        name = self.form_required('name')
        value = self.form_required('value')
        if name not in Preference.pref_names:
            self.render_json({'status': 1, 'msg': 'no such preference'})
            return
        UserPrefs.store_preference(self.user.user_id(), name, value)
        self.render_json({'status': 0})

class Prefs(InteractiveHandler):

    requires_login = True

    def get(self):
        my_prefs = self.load_prefs()
        defined_prefs = sorted(Preference.all_prefs, key=lambda x: x.display)

        all_prefs = []
        for pref in defined_prefs:
            d = {'ref': pref, 'mine': my_prefs[pref.name]}
            all_prefs.append(d)

            self.env['message'] = 'sorry, can\'t alter these yet'
        self.env['all_prefs'] = all_prefs
        self.render_template('prefs.html')

add_route(Prefs, '/prefs')
add_route(UpdatePrefs, '/ajax/prefs')
Example #5
0
import re

from lexigraph.view import add_route
from lexigraph.handler import SessionHandler
class GraphQuery(SessionHandler):

    requires_login = True

    def initialize(self, request, response):
        super(GraphQuery, self).initialize(request, response)
        response.headers['Content-Type'] = 'application/json'

    def get(self):
        q = self.request.get('q') or ''
        tags = set(x.strip() for x in q.split(',') if x.strip())
        datasets = TagQueryCache().select_by_tags(self.account, self.user, tags)
        self.render_json({'status': True, 'datasets': datasets})

add_route(GraphQuery, '/graph/query')
Example #6
0
    requires_login = True

    def check_allowed(self, datasets):
        count = 0
        for ds in model.DataSet.all().filter('account =', self.account).filter('name IN', datasets):
            count += 1
            if not ds.is_allowed(user=self.user, read=True, write=True):
                self.session['error_message'] = 'Insufficient privileges'
                self.redirect('/dashboard')
        if count < len(set(datasets)):
            self.session['error_message'] = 'Failed to find all specified datasets'
            self.redirect('/dashboard')

    def post(self):
        name = self.form_required('name')
        datasets = self.form_required('datasets')
        datasets = [x.strip() for x in datasets.split(',')]
        self.check_allowed(datasets)

        # TODO: validate tags
        tags = self.form_required('tags')
        tags = set(x.strip() for x in tags.split(','))
        tags.add('composite')

        composite = model.CompositeDataSet.create(name=name, names=datasets, tags=list(tags), account=self.account)
        composite.put()

        self.redirect('/dashboard')

add_route(NewCompositeDataSet, '/new/composite_dataset')
Example #7
0
import datetime
from lexigraph.view import add_route
from lexigraph.handler import InteractiveHandler

class ShowUnixtime(InteractiveHandler):

    def initialize(self, request, response):
        super(ShowUnixtime, self).initialize(request, response)
        response.headers['Content-Type'] = 'text/plain'

    def get(self):
        self.response.out.write(datetime.datetime.now().strftime('%s'))

add_route(ShowUnixtime, '/debug/unixtime')
Example #8
0
from lexigraph.view import add_route
from lexigraph.handler import TagsMixin, InteractiveHandler
from lexigraph import model
from django.utils import simplejson
import contextlib

class Dashboard(TagsMixin, InteractiveHandler):

    requires_login = True

    def get(self):
        if self.account is None:
            self.log.info('No accounts set up for user, redirecting')
            self.redirect('/account')
            return
        self.load_prefs()
        self.env['groups'] = list(model.AccessGroup.groups_for_user(self.account))
        self.env['dashboard_graphs'] = self.datasets_by_tags(['dashboard'])
        self.env['any_datasets'] = bool(model.DataSet.all().filter('account =', self.account).fetch(1))
        self.render_template('dashboard.html')
        
add_route(Dashboard, '/dashboard')
Example #9
0
import datetime

from lexigraph.view import add_route
from lexigraph import model
from lexigraph.handler import InteractiveHandler

from lexigraph.view.cron import CronRequestHandler

class FixAccounts(CronRequestHandler):
    """Add a display_name to accounts without one."""

    def get(self):
        for account in model.Account.all():
            if not getattr(account, 'display_name', None):
                account.display_name = account.name
                account.put()
            if not getattr(account, 'last_login', None):
                account.last_login = datetime.datetime(2000, 1, 1)
                account.put()

add_route(FixAccounts, '/adhoc/fixaccounts')
Example #10
0
        def new_composite(name, datasets, tags=[]):
            dataset_ids = [ds.key().id() for ds in datasets]
            model.CompositeDataSet(name=name, datasets=dataset_ids, tags=tags, account=self.account, hostname=datasets[0].hostname).put()

        if populate == 'on':
            new_composite('load', [
                    new_dataset('load1', 'max', ['load']),
                    new_dataset('load5', 'max', ['load']),
                    new_dataset('load15', 'max', ['load']),
                    new_dataset('cpu_count', 'new', ['load', 'cpu'])],
                          ['dashboard', 'load'])
            new_composite('cpu', [
                    new_dataset('cpu_total', 'min', ['cpu']),
                    new_dataset('cpu_user', 'max', ['cpu']),
                    new_dataset('cpu_system', 'max', ['cpu']),
                    new_dataset('cpu_nice', 'max', ['cpu']),
                    new_dataset('cpu_iowait', 'max', ['cpu'])],
                          ['dashboard', 'cpu'])
            new_composite('memory', [
                    new_dataset('mem_total', 'new', ['mem']),
                    new_dataset('mem_buffers', 'new', ['mem']),
                    new_dataset('mem_cached', 'new', ['mem']),
                    new_dataset('mem_resident', 'new', ['mem']),
                    new_dataset('mem_used', 'new', ['mem'])],
                          ['dashboard', 'mem'])

        self.redirect('/dashboard')

add_route(NewHost, '/new/host')
Example #11
0
            else:
                t = now
            ts.append(t)
        return ts

    @encode_json
    def post(self):
        """Add one or more DataPoints. To add multiple points from a single
        request, you simply repeat the dataset/value/timestamp form variables.
        """
        datasets = self.request.get_all('dataset')
        values = self.request.get_all('value')
        timestamps = self.request.get_all('timestamp')

        assert datasets

        if not timestamps:
            timestamps = [0 for x in xrange(len(datasets))]
        assert len(datasets) == len(values)
        assert len(datasets) == len(timestamps)

        values = [float(v) for v in values]
        datasets = self.get_datasets(datasets)
        timestamps = self.get_timestamps(timestamps)

        for ds, v, t in zip(datasets, values, timestamps):
            ds.add_points(v, t)
        return self.add_status({}, StatusCodes.OK)

add_route(CreatePoint, '/api/new/datapoint')
Example #12
0
    requires_login = True

    def post(self):
        # XXX: no security here!
        name = self.form_required('account')
        account = maybe_one(model.Account.all().filter('name =', name))
        if account:
            model.ActiveAccount.set_active_account(self.user, account)
            self.redirect('/dashboard')
        else:
            self.session['error_message'] = 'invalid choice'
            self.redirect('/choose/account')

class UpdateAccount(InteractiveHandler):

    requires_login = True

    def get(self):
        mail = self.user.email()
        if config.whitelisted_emails and mail not in config.whitelisted_emails:
            self.session['error_message'] = 'Sorry, your email (%s) hasn\'t been whitelisted. Ask Evan if you need access.' % (mail,)
            self.redirect('/')
        self.env['accounts'] = list(model.Account.all().filter('owner =', self.user))
        self.env['support_address'] = lexigraph.mail.support_address
        self.render_template('account.html')


add_route(NewAccount, '/new/account')
add_route(ChooseAccount, '/choose/account')
add_route(UpdateAccount, '/account')
Example #13
0
from google.appengine.api.labs import taskqueue

from lexigraph.view.cron._common import *
from lexigraph.view import add_route
from lexigraph import model

class DataPointTrim(CronRequestHandler):

    def get(self):
        for s in model.DataSeries.all():
            key = s.key()
            taskqueue.add(url='/tasks/trim_series', params={'series_key': key})
            self.response.out.write('queued series_key = %r' % (key,))

add_route(DataPointTrim, '/cron/trim/datapoints')
Example #14
0
from lexigraph.view import add_route
from lexigraph.handler import SessionHandler, TagsMixin

class RenderGraph(TagsMixin, SessionHandler):

    requires_login = True

    def get(self):
        tags = [x.strip() for x in self.request.get('tags').split(',')]
        self.env['names'] = names = self.datasets_by_tags(tags)
        self.render_ajax('ajax/graphs.html', extra={'names': names})
        
add_route(RenderGraph, '/ajax/graphs')
Example #15
0
    def post(self):
        dataset = self.get_dataset()
        assert dataset.is_allowed(self.user, delete=True)

        if self.env['is_composite']:
            dataset.delete()
            self.redirect('/dashboard')

        # XXX: this is racy (i.e. if someone creates points while we're deleting
        # the dataset). This ought to be amended by a cron job that looks for
        # abandoned points, or by implementing locking.

        # delete all of the data points
        for s in dataset.series():
            while True:
                points = list(model.DataPoint.all().filter('series =', s))
                if not points:
                    break
                for p in points:
                    p.delete()
            s.delete()
        for ac in model.AccessControl.all().filter('dataset =', dataset):
            ac.delete()
        dataset.delete()
        self.redirect('/dashboard')

add_route(NewDataSet, '/new/dataset')
add_route(EditDataSet, '/edit/dataset')
add_route(DeleteDataSet, '/delete/dataset')
Example #16
0
from lexigraph.view import add_route
from lexigraph.handler import SessionHandler
from google.appengine.api.users import create_logout_url

class Logout(SessionHandler):

    def get(self):
        if self.user:
            self.session.clear_all()
            self.redirect(create_logout_url('/'), permanent=False)
        else:
            self.redirect('/', permanent=False)

add_route(Logout, '/logout')