Skip to content

Commit

Permalink
initial pyinstrument integration
Browse files Browse the repository at this point in the history
Signed-off-by: Nischay Ram Mamidi <NischayPro@gmail.com>
  • Loading branch information
Nischay-Pro committed Jun 13, 2023
1 parent 4185880 commit 6311f80
Show file tree
Hide file tree
Showing 9 changed files with 50 additions and 9 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -37,3 +37,5 @@ db_schema.png

.coverage
htmlcov
test/*
profile_reports/*
9 changes: 9 additions & 0 deletions documentation/configuration.rst
Expand Up @@ -102,6 +102,15 @@ Whether to turn on a feature which times requests made through FlexMeasures. Int

Default: ``False``

FLEXMEASURES_PROFILE_PYINSTRUMENT
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Whether to turn on a feature which profiles the Flask API endpoints using `pyinstrument`. Interesting for developers.

The profiling results are stored in the ``profile_reports`` folder in the instance directory.

Default: ``False``


UI
--
Expand Down
26 changes: 26 additions & 0 deletions flexmeasures/app.py
Expand Up @@ -5,6 +5,9 @@
from __future__ import annotations

import time
import os
from pathlib import Path
from datetime import date

from flask import Flask, g, request
from flask.cli import load_dotenv
Expand Down Expand Up @@ -96,6 +99,8 @@ def create( # noqa C901
app.config["SECURITY_PASSWORD_SALT"] = app.config["SECRET_KEY"]
if app.env not in ("documentation", "development"):
SSLify(app)
if app.config.get("FLEXMEASURES_PROFILE_PYINSTRUMENT", False):
Path("profile_reports").mkdir(parents=True, exist_ok=True)

# Register database and models, including user auth security handlers

Expand Down Expand Up @@ -150,6 +155,27 @@ def create( # noqa C901
def before_request():
if app.config.get("FLEXMEASURES_PROFILE_REQUESTS", False):
g.start = time.time()
if app.config.get("FLEXMEASURES_PROFILE_PYINSTRUMENT", False):
import pyinstrument

g.profiler = pyinstrument.Profiler()
g.profiler.start()

@app.after_request
def after_request(response):
if app.config.get("FLEXMEASURES_PROFILE_PYINSTRUMENT", False):
g.profiler.stop()
output_html = g.profiler.output_html(timeline=True)
endpoint = request.endpoint
if endpoint is None:
endpoint = "unknown"
today = date.today()
profile_filename = f"pyinstrument_{endpoint}.html"
profile_output_path = Path("profile_reports", today.strftime("%Y-%m-%d"))
profile_output_path.mkdir(parents=True, exist_ok=True)
with open(os.path.join(profile_output_path, profile_filename), "w+") as f:
f.write(output_html)
return response

@app.teardown_request
def teardown_request(exception=None):
Expand Down
1 change: 1 addition & 0 deletions flexmeasures/utils/config_defaults.py
Expand Up @@ -131,6 +131,7 @@ class Config(object):
FLEXMEASURES_API_SUNSET_ACTIVE: bool = False # if True, sunset endpoints return 410 (Gone) responses; if False, they return 404 (Not Found) responses or will work as before, depending on whether the current FlexMeasures version still contains the endpoint logic
FLEXMEASURES_API_SUNSET_DATE: str | None = None # e.g. 2023-05-01
FLEXMEASURES_API_SUNSET_LINK: str | None = None # e.g. https://flexmeasures.readthedocs.io/en/latest/api/introduction.html#deprecation-and-sunset
FLEXMEASURES_PROFILE_PYINSTRUMENT: bool = False


# names of settings which cannot be None
Expand Down
4 changes: 2 additions & 2 deletions requirements/app.txt
@@ -1,6 +1,6 @@
#
# This file is autogenerated by pip-compile with python 3.9
# To update, run:
# This file is autogenerated by pip-compile with Python 3.9
# by the following command:
#
# pip-compile --output-file=requirements/app.txt requirements/app.in
#
Expand Down
3 changes: 2 additions & 1 deletion requirements/dev.in
Expand Up @@ -10,4 +10,5 @@ flake8-blind-except
mypy
pytest-runner
setuptools_scm
watchdog
watchdog
pyinstrument
6 changes: 4 additions & 2 deletions requirements/dev.txt
@@ -1,6 +1,6 @@
#
# This file is autogenerated by pip-compile with python 3.9
# To update, run:
# This file is autogenerated by pip-compile with Python 3.9
# by the following command:
#
# pip-compile --output-file=requirements/dev.txt requirements/dev.in
#
Expand Down Expand Up @@ -52,6 +52,8 @@ pycodestyle==2.8.0
# via flake8
pyflakes==2.4.0
# via flake8
pyinstrument==4.5.0
# via -r requirements/dev.in
pytest-runner==6.0.0
# via -r requirements/dev.in
pyyaml==6.0
Expand Down
4 changes: 2 additions & 2 deletions requirements/docs.txt
@@ -1,6 +1,6 @@
#
# This file is autogenerated by pip-compile with python 3.9
# To update, run:
# This file is autogenerated by pip-compile with Python 3.9
# by the following command:
#
# pip-compile --output-file=requirements/docs.txt requirements/docs.in
#
Expand Down
4 changes: 2 additions & 2 deletions requirements/test.txt
@@ -1,6 +1,6 @@
#
# This file is autogenerated by pip-compile with python 3.9
# To update, run:
# This file is autogenerated by pip-compile with Python 3.9
# by the following command:
#
# pip-compile --output-file=requirements/test.txt requirements/test.in
#
Expand Down

0 comments on commit 6311f80

Please sign in to comment.