Example #1
0
class Middleware:
    def __init__(self, get_response):
        self.get_response = get_response
        self.recorder = Recorder()

    def __call__(self, request):
        if self.recorder.enabled:
            start = time.monotonic()
            call_event = HttpRequestEvent(
                request_method=request.method,
                path_info=request.path_info,
                protocol=request.META['SERVER_PROTOCOL'])
            self.recorder.add_event(call_event)

        response = self.get_response(request)

        if self.recorder.enabled:
            duration = time.monotonic() - start
            return_event = HttpResponseEvent(
                parent_id=call_event.id,
                elapsed=duration,
                status_code=response.status_code,
                mime_type=response.get('Content-Type', None) or 'unknown')
            self.recorder.add_event(return_event)

        return response
Example #2
0
class ExecuteWrapper:
    def __init__(self):
        self.recorder = Recorder()

    def __call__(self, execute, sql, params, many, context):
        start = time.monotonic()
        try:
            return execute(sql, params, many, context)
        finally:
            if self.recorder.enabled:
                stop = time.monotonic()
                duration = stop - start
                # Note this logic is based on django.db.backends.utils.CursorDebugWrapper.
                if many:
                    # Sometimes the same query is executed with different parameter sets.
                    # Instead of substituting them all, just say how many times it was run.
                    try:
                        times = len(params)
                    except TypeError:
                        times = '?'
                    sql = '%s times %s' % (times, sql)
                else:
                    db = context['connection']
                    cursor = context['cursor']
                    sql = db.ops.last_executed_query(cursor, sql, params)
                call_event = SqlEvent(sql)
                self.recorder.add_event(call_event)
                return_event = ReturnEvent(parent_id=call_event.id,
                                           elapsed=duration)
                self.recorder.add_event(return_event)
Example #3
0
def capture_sql_call(conn, cursor, statement, parameters, context,
                     executemany):
    """Capture SQL query callinto appmap."""
    recorder = Recorder()
    if is_instrumentation_disabled():
        # We must be in the middle of fetching object representation.
        # Don't record this query in the appmap.
        pass
    elif recorder.enabled:
        Metadata.add_framework('SQLAlchemy', sqlalchemy.__version__)
        if executemany:
            # Sometimes the same query is executed with different parameter sets.
            # Instead of substituting them all, just say how many times it was run.
            try:
                times = len(parameters)
            except TypeError:
                times = '?'
            sql = '-- %s times\n%s' % (times, statement)
        else:
            sql = statement
        dialect = conn.dialect
        call_event = SqlEvent(sql,
                              vendor=dialect.name,
                              version=dialect.server_version_info)
        recorder.add_event(call_event)
        setattr(context, 'appmap', {
            'start_time': time.monotonic(),
            'call_event_id': call_event.id
        })
 def events():
     """Enables appmap recording and allows examining events."""
     rec = Recorder()
     rec.events.clear()
     rec.enabled = True
     yield rec.events
     rec.enabled = False
     rec.events.clear()
def events():
    rec = Recorder()
    rec.events().clear()
    rec.enabled = True
    yield rec.events()
    rec.enabled = False
    rec.events().clear()
Example #6
0
def capture_sql(conn, cursor, statement, parameters, context, executemany):
    """Capture SQL query return into appmap."""
    recorder = Recorder()
    if is_instrumentation_disabled():
        # We must be in the middle of fetching object representation.
        # Don't record this query in the appmap.
        pass
    elif recorder.enabled:
        stop = time.monotonic()
        duration = stop - context.appmap['start_time']
        return_event = ReturnEvent(parent_id=context.appmap['call_event_id'],
                                   elapsed=duration)
        del context.appmap
        recorder.add_event(return_event)
Example #7
0
    def before_request(self):
        if self.recording.is_running() and request.path != self.record_url:
            call_event = HttpRequestEvent(
                request_method=request.method,
                path_info=request.path,
                normalized_path_info=request.url_rule.rule,
                protocol=request.environ.get('SERVER_PROTOCOL'))
            Recorder().add_event(call_event)

            g.appmap_request_event = call_event
            g.appmap_request_start = time.monotonic()
Example #8
0
    def after_request(self, response):
        if self.recording.is_running() and request.path != self.record_url:
            parent_id = g.appmap_request_event.id
            duration = time.monotonic() - g.appmap_request_start

            return_event = HttpResponseEvent(parent_id=parent_id,
                                             elapsed=duration,
                                             status_code=response.status_code,
                                             mime_type=response.content_type)
            Recorder().add_event(return_event)

        return response
Example #9
0
    def after_request(self, response):
        if self.recording.is_running() and request.path != self.record_url:
            appctx = _app_ctx_stack.top
            parent_id = appctx.appmap_request_event.id
            duration = time.monotonic() - appctx.appmap_request_start

            return_event = HttpServerResponseEvent(
                parent_id=parent_id,
                elapsed=duration,
                status_code=response.status_code,
                headers=response.headers)
            Recorder().add_event(return_event)

        return response
Example #10
0
class ExecuteWrapper:
    def __init__(self):
        self.recorder = Recorder()

    def __call__(self, execute, sql, params, many, context):
        start = time.monotonic()
        try:
            return execute(sql, params, many, context)
        finally:
            if is_instrumentation_disabled():
                # We must be in the middle of fetching object representation.
                # Don't record this query in the appmap.
                pass
            elif self.recorder.enabled:
                add_metadata()
                stop = time.monotonic()
                duration = stop - start
                conn = context['connection']
                # Note this logic is based on django.db.backends.utils.CursorDebugWrapper.
                if many:
                    # Sometimes the same query is executed with different parameter sets.
                    # Instead of substituting them all, just say how many times it was run.
                    try:
                        times = len(params)
                    except TypeError:
                        times = '?'
                    sql = '%s times %s' % (times, sql)
                else:
                    cursor = context['cursor']
                    sql = conn.ops.last_executed_query(cursor, sql, params)
                call_event = SqlEvent(sql,
                                      vendor=conn.vendor,
                                      version=database_version(conn))
                self.recorder.add_event(call_event)
                return_event = ReturnEvent(parent_id=call_event.id,
                                           elapsed=duration)
                self.recorder.add_event(return_event)
Example #11
0
    def render(self, orig, *args, **kwargs):
        """Calls the original implementation.

        If recording is enabled, adds appropriate TemplateEvent
        and ReturnEvent.
        """
        rec = Recorder()
        if rec.enabled:
            start = time.monotonic()
            call_event = TemplateEvent(self.filename, self)  # pylint: disable=no-member
            rec.add_event(call_event)
        try:
            return orig(self, *args, **kwargs)
        finally:
            if rec.enabled:
                rec.add_event(
                    ReturnEvent(call_event.id,
                                time.monotonic() - start))
Example #12
0
    def before_request(self):
        if self.recording.is_running() and request.path != self.record_url:
            Metadata.add_framework('flask', flask.__version__)
            np = None
            # See
            # https://github.com/pallets/werkzeug/blob/2.0.0/src/werkzeug/routing.py#L213
            # for a description of parse_rule.
            if request.url_rule:
                np = ''.join([
                    f'{{{p}}}' if c else p
                    for c, _, p in parse_rule(request.url_rule.rule)
                ])
            call_event = HttpServerRequestEvent(
                request_method=request.method,
                path_info=request.path,
                message_parameters=request_params(request),
                normalized_path_info=np,
                protocol=request.environ.get('SERVER_PROTOCOL'),
                headers=request.headers)
            Recorder().add_event(call_event)

            appctx = _app_ctx_stack.top
            appctx.appmap_request_event = call_event
            appctx.appmap_request_start = time.monotonic()
Example #13
0
 def __init__(self, get_response):
     self.get_response = get_response
     self.recorder = Recorder()
Example #14
0
 def __init__(self):
     self.recorder = Recorder()
Example #15
0
class Middleware:
    def __init__(self, get_response):
        self.get_response = get_response
        self.recorder = Recorder()

    def __call__(self, request):
        if not Env.current.enabled:
            return self.get_response(request)

        if request.path_info == '/_appmap/record':
            return self.recording(request)
        if self.recorder.enabled:
            add_metadata()
            start = time.monotonic()
            params = request_params(request)
            try:
                resolved = resolve(request.path_info)
                params.update(resolved.kwargs)
                normalized_path_info = normalize_path_info(
                    request.path_info, resolved)
            except Resolver404:
                # If the request was for a bad path (e.g. when an app
                # is testing 404 handling), resolving will fail.
                normalized_path_info = None

            call_event = HttpServerRequestEvent(
                request_method=request.method,
                path_info=request.path_info,
                message_parameters=params,
                normalized_path_info=normalized_path_info,
                protocol=request.META['SERVER_PROTOCOL'],
                headers=request.headers)
            self.recorder.add_event(call_event)

        try:
            response = self.get_response(request)
        except:
            if self.recorder.enabled:
                duration = time.monotonic() - start
                exception_event = ExceptionEvent(parent_id=call_event.id,
                                                 elapsed=duration,
                                                 exc_info=sys.exc_info())
                self.recorder.add_event(exception_event)
            raise

        if self.recorder.enabled:
            duration = time.monotonic() - start
            return_event = HttpServerResponseEvent(
                parent_id=call_event.id,
                elapsed=duration,
                status_code=response.status_code,
                headers=dict(response.items()))
            self.recorder.add_event(return_event)

        return response

    def recording(self, request):
        """Handle recording requests."""
        if request.method == 'GET':
            return JsonResponse({'enabled': self.recorder.enabled})
        if request.method == 'POST':
            if self.recorder.enabled:
                return HttpResponse('Recording is already in progress',
                                    status=409)
            self.recorder.clear()
            self.recorder.start_recording()
            return HttpResponse()

        if request.method == 'DELETE':
            if not self.recorder.enabled:
                return HttpResponse('No recording is in progress', status=404)

            self.recorder.stop_recording()
            return HttpResponse(generation.dump(self.recorder),
                                content_type='application/json')

        return HttpResponseBadRequest()