Skip to content

Commit

Permalink
Add SILKY_PYTHON_PROFILER_EXTENDED_FILE_NAME settings to generate mor…
Browse files Browse the repository at this point in the history
…e informative profile file name
  • Loading branch information
k4rl85 committed Jan 3, 2023
1 parent 5677fa8 commit 1be0b85
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 1 deletion.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,11 @@ SILKY_PYTHON_PROFILER_RESULT_PATH = '/path/to/profiles/'

A download button will become available with a binary `.prof` file for every request. This file can be used for further analysis using [snakeviz](https://github.com/jiffyclub/snakeviz) or other cProfile tools

To retrieve which endpoint generates a specific profile file it is possible to add a stub of the request path in the file name with the following:

```python
SILKY_PYTHON_PROFILER_EXTENDED_FILE_NAME = True
```

Silk can also be used to profile specific blocks of code/functions. It provides a decorator and a context
manager for this purpose.
Expand Down
21 changes: 21 additions & 0 deletions project/tests/test_collector.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from tests.util import DictStorage

from silk.collector import DataCollector
from silk.config import SilkyConfig

from .factories import RequestMinFactory

Expand Down Expand Up @@ -45,3 +46,23 @@ def test_finalise(self):
content = f.read()
self.assertTrue(content)
self.assertGreater(len(content), 0)

def test_profile_file_name(self):
request = RequestMinFactory()
DataCollector().configure(request)
expected_file_name_prefix = request.path.replace('/', '_').lstrip('_')
print(expected_file_name_prefix)

with self.subTest("With disabled extended file name"):
SilkyConfig().SILKY_PYTHON_PROFILER_EXTENDED_FILE_NAME = False
DataCollector().finalise()
file = DataCollector().request.prof_file
result_file_name = file.name.rsplit('/')[-1]
self.assertFalse(result_file_name.startswith(f"{expected_file_name_prefix}_"))

with self.subTest("With enabled extended file name"):
SilkyConfig().SILKY_PYTHON_PROFILER_EXTENDED_FILE_NAME = True
DataCollector().finalise()
file = DataCollector().request.prof_file
result_file_name = file.name.rsplit('/')[-1]
self.assertTrue(result_file_name.startswith(f"{expected_file_name_prefix}_"))
11 changes: 10 additions & 1 deletion silk/collector.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,8 @@ def finalise(self):
self.request.pyprofile = profile_text

if SilkyConfig().SILKY_PYTHON_PROFILER_BINARY:
file_name = self.request.prof_file.storage.get_available_name(f"{str(self.request.id)}.prof")
proposed_file_name = self._get_proposed_file_name()
file_name = self.request.prof_file.storage.get_available_name(proposed_file_name)
with self.request.prof_file.storage.open(file_name, 'w+b') as f:
marshal.dump(ps.stats, f)
self.request.prof_file = f.name
Expand Down Expand Up @@ -189,3 +190,11 @@ def finalise(self):

def register_silk_query(self, *args):
self.register_objects(TYP_SILK_QUERIES, *args)

def _get_proposed_file_name(self):
"""Retrieve the profile file name to be proposed to the storage"""

if SilkyConfig().SILKY_PYTHON_PROFILER_EXTENDED_FILE_NAME:
request_path = self.request.path.replace('/', '_').lstrip('_')
return f"{request_path}_{str(self.request.id)}.prof"
return f"{str(self.request.id)}.prof"
1 change: 1 addition & 0 deletions silk/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class SilkyConfig(metaclass=Singleton):
'SILKY_PYTHON_PROFILER': False,
'SILKY_PYTHON_PROFILER_FUNC': None,
'SILKY_STORAGE_CLASS': 'silk.storage.ProfilerResultStorage',
'SILKY_PYTHON_PROFILER_EXTENDED_FILE_NAME': False,
'SILKY_MIDDLEWARE_CLASS': 'silk.middleware.SilkyMiddleware',
'SILKY_JSON_ENSURE_ASCII': True,
'SILKY_ANALYZE_QUERIES': False,
Expand Down

0 comments on commit 1be0b85

Please sign in to comment.