1 new commit in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/commits/63a81f213633/ Changeset: 63a81f213633 User: carlfeberhard Date: 2014-04-09 22:15:00 Summary: Metrics API: allow posting of metrics sending to app.trace_logger.log if available Affected #: 2 files diff -r fbe5f3970ac2f1fe32710a4962a175de7264c2be -r 63a81f21363325ebbefc321350315804b15bc79e lib/galaxy/webapps/galaxy/api/metrics.py --- /dev/null +++ b/lib/galaxy/webapps/galaxy/api/metrics.py @@ -0,0 +1,131 @@ +""" +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 import web +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__ ) + + +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 + 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' : json.from_json_string( 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 {} + diff -r fbe5f3970ac2f1fe32710a4962a175de7264c2be -r 63a81f21363325ebbefc321350315804b15bc79e lib/galaxy/webapps/galaxy/buildapp.py --- a/lib/galaxy/webapps/galaxy/buildapp.py +++ b/lib/galaxy/webapps/galaxy/buildapp.py @@ -304,10 +304,22 @@ new={ 'install_repository_revision' : 'POST' }, parent_resources=dict( member_name='tool_shed_repository', collection_name='tool_shed_repositories' ) ) + + # ==== Trace/Metrics Logger # Connect logger from app if app.trace_logger: webapp.trace_logger = app.trace_logger + # metrics logging API + #webapp.mapper.connect( "index", "/api/metrics", + # controller="metrics", action="index", conditions=dict( method=["GET"] ) ) + #webapp.mapper.connect( "show", "/api/metrics/{id}", + # controller="metrics", action="show", conditions=dict( method=["GET"] ) ) + webapp.mapper.connect( "create", "/api/metrics", + controller="metrics", action="create", conditions=dict( method=["POST"] ) ) + + + # ==== Done # Indicate that all configuration settings have been provided webapp.finalize_config() Repository URL: https://bitbucket.org/galaxy/galaxy-central/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email.