Source code for galaxy.webapps.galaxy.api.metrics

"""
API operations for for querying and recording user metrics from some client
(typically a user's browser).
"""
#TODO: facade or adapter to fluentd

import datetime

from galaxy import exceptions
from galaxy.web import require_admin
from galaxy.web import _future_expose_api as expose_api
from galaxy.web import _future_expose_api_anonymous as expose_api_anonymous

from galaxy.web.base.controller import BaseAPIController

from galaxy.util import json

import logging
log = logging.getLogger( __name__ )


[docs]class MetricsController( BaseAPIController ): def __init__( self, app ): super( MetricsController, self ).__init__( app ) #: set to true to send additional debugging info to the log self.debugging = True #def _decode_id( self, trans, id ): # try: # return trans.security.decode_id( id ) # except: # raise exceptions.MalformedId( "Malformed id ( %s ) specified, unable to decode" # % ( str( id ) ), type='error' ) def _deserialize_isoformat_date( self, datestring ): """ Convert ISO formatted date string into python datetime. """ return datetime.datetime.strptime( datestring, "%Y-%m-%dT%H:%M:%S.%fZ" ) #@expose_api #@require_admin #def index( self, trans, **kwd ): # """ # """ # returned = [] # return returned #@expose_api #@require_admin #def show( self, trans, id, **kwd ): # """ # """ # returned = {} # return returned @expose_api_anonymous
[docs] def create( self, trans, payload, **kwd ): """ create( trans, payload ) * POST /api/metrics: record any metrics sent and return some status object .. note:: Anonymous users can post metrics :type payload: dict :param payload: (optional) dictionary structure containing: * metrics: a list containing dictionaries of the form: ** namespace: label indicating the source of the metric ** time: isoformat datetime when the metric was recorded ** level: an integer representing the metric's log level ** args: a json string containing an array of extra data :rtype: dict :returns: status object """ user_id = trans.user.id if trans.user else None session_id = trans.galaxy_session.id if trans.galaxy_session else None parsed_gen = self._parse_metrics( payload.get( 'metrics', None ), user_id, session_id ) self._send_metrics( trans, parsed_gen ) response = self._get_server_pong( trans ) return response #TODO: move the following to DAO/Manager object
def _parse_metrics( self, metrics, user_id=None, session_id=None ): """ Return a generator yielding the each given metric as a tuple: * label: the namespace of the metric * time: datetime of the metric's creation * kwargs: a dictionary containing: ** level: the log level of the metric ** user: the user associated with the metric (will be None if anonymous user) ** session: the session of the current user """ metrics = metrics or [] for metric in metrics: label = metric[ 'namespace' ] time = self._deserialize_isoformat_date( metric[ 'time' ] ) kwargs = { 'level' : metric[ 'level' ], 'args' : metric[ 'args' ], 'user' : user_id, 'session' : session_id } yield ( label, time, kwargs ) def _send_metrics( self, trans, metrics ): """ Send metrics to the app's `trace_logger` if set and send to `log.debug` if this controller if `self.debugging`. Precondition: metrics are parsed and in proper format. """ if trans.app.trace_logger: for label, time, kwargs in metrics: trans.app.trace_logger.log( label, time=int( time ), **kwargs ) elif self.debugging: for label, time, kwargs in metrics: log.debug( '%s %s %s', label, time, kwargs ) def _get_server_pong( self, trans ): """ Return some status message or object. For future use. """ return {}