Beispiel #1
0
class HTTPFrontend(object):
    """This is a lightweight embedded HTTP server that runs inside a mailsync
    process. It allows you can programmatically interact with the process:
    to get profile/memory/load metrics, or to schedule new account syncs."""
    def __init__(self, sync_service, port, trace_greenlets, profile):
        self.sync_service = sync_service
        self.port = port
        self.profiler = ProfileCollector() if profile else None
        self.tracer = GreenletTracer() if trace_greenlets else None

    def start(self):
        if self.tracer is not None:
            self.tracer.start()

        if self.profiler is not None:
            self.profiler.start()

        app = self._create_app()

        gevent.spawn(run_simple, '0.0.0.0', self.port, app,
                     request_handler=_QuietHandler)

    def _create_app(self):
        app = Flask(__name__)

        @app.route('/unassign', methods=['POST'])
        def unassign_account():
            account_id = request.json['account_id']
            ret = self.sync_service.stop_sync(account_id)
            if ret:
                return 'OK'
            else:
                return 'Account not assigned to this process', 409

        @app.route('/profile')
        def profile():
            if self.profiler is None:
                return 'Profiling disabled\n', 404
            resp = self.profiler.stats()
            if request.args.get('reset ') in (1, 'true'):
                self.profiler.reset()
            return resp

        @app.route('/load')
        def load():
            if self.tracer is None:
                return 'Load tracing disabled\n', 404
            resp = jsonify(self.tracer.stats())
            if request.args.get('reset ') in (1, 'true'):
                self.tracer.reset()
            return resp

        @app.route('/mem')
        def mem():
            objs = muppy.get_objects()
            summ = summary.summarize(objs)
            return '\n'.join(summary.format_(summ)) + '\n'

        return app
def test_greenlet_tracer(monkeypatch):
    logging_interval = 5
    greenlet_tracer = GreenletTracer(logging_interval=logging_interval)

    logger_mock = mock.Mock()
    get_logger_mock = mock.Mock(return_value=logger_mock)
    monkeypatch.setattr("inbox.instrumentation.get_logger", get_logger_mock)

    greenlet_tracer.start()

    time.sleep(logging_interval * 1.5)

    (call, ) = logger_mock.method_calls
    method, args, kwargs = call
    assert method == "info"
    assert args == ("greenlet stats", )
    assert kwargs["total_time"] >= logging_interval
    assert kwargs["pending_avgs"] == {
        1: 0,
        5: 0,
        15: 0
    }  # always 0 after one cycle

    greenlet_tracer.stop()
Beispiel #3
0
class HTTPFrontend(object):
    """This is a lightweight embedded HTTP server that runs inside a mailsync
    process. It allows you can programmatically interact with the process:
    to get profile/memory/load metrics, or to schedule new account syncs."""

    def __init__(self, sync_service, port, trace_greenlets, profile):
        self.sync_service = sync_service
        self.port = port
        self.profiler = ProfileCollector() if profile else None
        self.tracer = GreenletTracer() if trace_greenlets else None

    def start(self):
        if self.tracer is not None:
            self.tracer.start()

        if self.profiler is not None:
            self.profiler.start()

        app = self._create_app()

        # We need to spawn an OS-level thread because we don't want a stuck
        # greenlet to prevent us to access the web API.
        gevent._threading.start_new_thread(run_simple, ('0.0.0.0', self.port, app),
                                           {"request_handler": _QuietHandler})

    def _create_app(self):
        app = Flask(__name__)

        @app.route('/unassign', methods=['POST'])
        def unassign_account():
            account_id = request.json['account_id']
            ret = self.sync_service.stop_sync(account_id)
            if ret:
                return 'OK'
            else:
                return 'Account not assigned to this process', 409

        @app.route('/profile')
        def profile():
            if self.profiler is None:
                return 'Profiling disabled\n', 404
            resp = self.profiler.stats()
            if request.args.get('reset ') in (1, 'true'):
                self.profiler.reset()
            return resp

        @app.route('/load')
        def load():
            if self.tracer is None:
                return 'Load tracing disabled\n', 404
            resp = jsonify(self.tracer.stats())
            if request.args.get('reset ') in (1, 'true'):
                self.tracer.reset()
            return resp

        @app.route('/mem')
        def mem():
            objs = muppy.get_objects()
            summ = summary.summarize(objs)
            return '\n'.join(summary.format_(summ)) + '\n'

        return app
Beispiel #4
0
 def __init__(self, sync_service, port, trace_greenlets, profile):
     self.sync_service = sync_service
     self.port = port
     self.profiler = ProfileCollector() if profile else None
     self.tracer = GreenletTracer() if trace_greenlets else None
Beispiel #5
0
 def __init__(self, sync_service, port, trace_greenlets, profile):
     self.sync_service = sync_service
     self.port = port
     self.profiler = ProfileCollector() if profile else None
     self.tracer = GreenletTracer() if trace_greenlets else None
Beispiel #6
0
class HTTPFrontend(object):
    """This is a lightweight embedded HTTP server that runs inside a mailsync
    process. It allows you can programmatically interact with the process:
    to get profile/memory/load metrics, or to schedule new account syncs."""

    def __init__(self, sync_service, port, trace_greenlets, profile):
        self.sync_service = sync_service
        self.port = port
        self.profiler = ProfileCollector() if profile else None
        self.tracer = GreenletTracer() if trace_greenlets else None

    def start(self):
        if self.tracer is not None:
            self.tracer.start()

        if self.profiler is not None:
            self.profiler.start()

        app = self._create_app()

        # We need to spawn an OS-level thread because we don't want a stuck
        # greenlet to prevent us to access the web API.
        gevent._threading.start_new_thread(run_simple, ("0.0.0.0", self.port, app), {"request_handler": _QuietHandler})

    def _create_app(self):
        app = Flask(__name__)

        @app.route("/unassign", methods=["POST"])
        def unassign_account():
            account_id = request.json["account_id"]
            ret = self.sync_service.stop_sync(account_id)
            if ret:
                return "OK"
            else:
                return "Account not assigned to this process", 409

        @app.route("/profile")
        def profile():
            if self.profiler is None:
                return "Profiling disabled\n", 404
            resp = self.profiler.stats()
            if request.args.get("reset ") in (1, "true"):
                self.profiler.reset()
            return resp

        @app.route("/load")
        def load():
            if self.tracer is None:
                return "Load tracing disabled\n", 404
            resp = jsonify(self.tracer.stats())
            if request.args.get("reset ") in (1, "true"):
                self.tracer.reset()
            return resp

        @app.route("/mem")
        def mem():
            objs = muppy.get_objects()
            summ = summary.summarize(objs)
            return "\n".join(summary.format_(summ)) + "\n"

        return app