Skip to content

Commit

Permalink
Merge pull request #1966 from DSD-DBS/profiling
Browse files Browse the repository at this point in the history
perf: Add profiling option for backend routes
  • Loading branch information
MoritzWeber0 authored Nov 7, 2024
2 parents 3c5c1fd + 392fe3c commit e8cb5e1
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/openapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ jobs:
- name: Run openapi-generator for target
working-directory: ./backend
run: make openapi
- name: Clear configuration
run: rm backend/config/config.yaml
- name: Move openapi schema file
run: mv /tmp/openapi.json /tmp/openapi2.json
- name: Checkout base
Expand Down
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ repos:
- types-lxml
- cryptography
- types-croniter
- pyinstrument
- repo: local
hooks:
- id: pylint
Expand Down
16 changes: 16 additions & 0 deletions backend/capellacollab/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,22 @@ async def shutdown():
)


if config.logging.profiling:
import pyinstrument

@app.middleware("http")
async def profile_request(request: fastapi.Request, call_next):
profiling = request.query_params.get("profile", False)
if profiling:
profiler = pyinstrument.Profiler(async_mode="enabled")
profiler.start()
await call_next(request)
profiler.stop()
return responses.HTMLResponse(profiler.output_html())
else:
return await call_next(request)


@app.get(
"/docs", response_class=responses.RedirectResponse, include_in_schema=False
)
Expand Down
4 changes: 4 additions & 0 deletions backend/capellacollab/config/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,10 @@ class LoggingConfig(BaseConfig):
description="The path to the log file (saved as 'backend.log').",
examples=["logs/"],
)
profiling: bool = pydantic.Field(
default=False,
description="Enable profiling of requests.",
)


class RequestsConfig(BaseConfig):
Expand Down
1 change: 1 addition & 0 deletions backend/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ dev = [
"aioresponses",
"types-lxml",
"types-croniter",
"pyinstrument",
]

[tool.black]
Expand Down
38 changes: 38 additions & 0 deletions docs/docs/development/backend/profiling.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<!--
~ SPDX-FileCopyrightText: Copyright DB InfraGO AG and contributors
~ SPDX-License-Identifier: Apache-2.0
-->

# Profile Backend Routes

Profiling can be useful if you want to examine the performance of specific
backend routes.

## Enable profiling

In the `config.yaml`, set the `logging.profiling` key to `True`. Then, call the
route you want to profile with the `profile` query parameter set to `True`.

For example, to profile the `/api/v1/metadata` route, you would call
`/api/v1/metadata?profile=True` in the browser. It will return a HTML report.

!!! info

Synchronous routes are not supported properly. If you want to profile a
synchronous route, add `async` to the route definition.

```
@router.get(...)
def metadata():
...
```

becomes

```
@router.get(...)
async def metadata():
...
```

[More Information on GitHub](https://github.com/joerick/pyinstrument/issues/257)
1 change: 1 addition & 0 deletions docs/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ nav:
- Introduction: development/index.md
- Backend:
- Code Style: development/backend/code-style.md
- Profiling: development/backend/profiling.md
- Technology Overview: development/backend/technology.md
- Extension Modules: development/backend/extensions.md
- Exception Handling: development/backend/exception.md
Expand Down

0 comments on commit e8cb5e1

Please sign in to comment.