Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add py-spy profiler support #137

Merged
merged 1 commit into from
Jun 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 19 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,19 @@ connect_troncos_logging_celery_signals()

## Profiling

### Enabling the profiler
### Enabling the continuous py-spy profiler

Start the profiler by running the `start_py_spy_profiler` method early in your application. This is
typically done in `settings.py` of you want to profile a Django application, or in `__init__.py`
in the root project package.

```python
from troncos.profiling import start_py_spy_profiler

start_py_spy_profiler(server_address="http://127.0.0.1:4100")
```

### Enabling the ddtrace profiler

Start the profiler by importing the profiler module early in your application. This is
typically done in `settings.py` of you want to profile a Django application, or in `__init__.py`
Expand All @@ -207,11 +219,11 @@ in the root project package.
import troncos.profiling.auto
```

### Setup profile endpoint
#### Setup profile endpoint

Use one of the methods bellow based on your selected framework.

#### Django
##### Django

Add the profile view to the url config.

Expand All @@ -225,7 +237,7 @@ urlpatterns = [
]
```

#### Starlette
##### Starlette

Add the profile view to your router.

Expand All @@ -239,7 +251,7 @@ routes = [
]
```

#### ASGI
##### ASGI

Mount the generic ASGI profiling application. There is no generic way to do this,
please check the relevant ASGI framework documentation.
Expand All @@ -255,15 +267,15 @@ app = FastAPI()
app.mount("/debug/pprof", profiling_asgi_app)
```

### Verify setup
#### Verify setup

You can verify that your setup works with the [pprof](https://github.com/google/pprof) cli:

```console
$ pprof -http :6060 "http://localhost:8080/debug/pprof"
```

### Enable scraping
#### Enable scraping

When you deploy your application, be sure to use the custom oda annotation for scraping:

Expand Down
136 changes: 105 additions & 31 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ opentelemetry-sdk = "1.18.0"
opentelemetry-exporter-otlp-proto-http = "1.18.0"
opentelemetry-exporter-otlp-proto-grpc = {version = "1.18.0", optional = true}
python-ipware = "^0.9.0"
pyroscope-io = "^0.8.3"

[tool.poetry.extras]
grpc = ["opentelemetry-exporter-otlp-proto-grpc"]
Expand Down
3 changes: 3 additions & 0 deletions troncos/profiling/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .pyroscope import start_py_spy_profiler

__all__ = ["start_py_spy_profiler"]
33 changes: 33 additions & 0 deletions troncos/profiling/pyroscope.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import pyroscope
from ddtrace import config


def start_py_spy_profiler(
*,
server_address: str,
tags: dict[str, str] | None = None,
enable_logging: bool = False,
) -> None:
"""Start the py-spy continuous profiler."""

app_name = config.service or "unknown-service"
profiler_tags = {
"app": app_name,
"env": config.env,
"version": config.version,
**config.tags,
}

if tags:
profiler_tags.update(tags)

pyroscope.configure(
app_name=app_name,
tags=profiler_tags,
server_address=server_address,
sample_rate=100,
detect_subprocesses=True,
oncpu=False,
gil_only=False,
enable_logging=enable_logging,
)