diff --git a/README.md b/README.md index efefdab7..1494f298 100644 --- a/README.md +++ b/README.md @@ -165,7 +165,14 @@ When enabled a graph visualisation generated using [gprof2dot](https://github.co -You can specify where to store the generated binary `.prof` files to a path of your choosing. You must ensure the specified directory exists. + +A custom storage class can be used for the saved the generated binary `.prof` files: + +```python +SILKY_STORAGE_CLASS = 'path.to.StorageClass' +``` + +The default storage class is `silk.storage.ProfilerResultStorage`, and when using that you can specify a path of your choosing. You must ensure the specified directory exists. ```python # If this is not set, MEDIA_ROOT will be used. diff --git a/project/tests/test_models.py b/project/tests/test_models.py index 406af69a..e9fa6502 100644 --- a/project/tests/test_models.py +++ b/project/tests/test_models.py @@ -10,6 +10,7 @@ from freezegun import freeze_time from silk import models +from silk.storage import ProfilerResultStorage from silk.config import SilkyConfig from .factories import RequestMinFactory, SQLQueryFactory, ResponseFactory @@ -199,6 +200,10 @@ def test_save_if_have_end_time(self): self.assertEqual(obj.end_time, date) self.assertEqual(obj.time_taken, 3000.0) + def test_prof_file_default_storage(self): + obj = models.Request(path='/some/path/', method='get') + self.assertEqual(obj.prof_file.storage.__class__, ProfilerResultStorage) + class ResponseTest(TestCase): diff --git a/silk/config.py b/silk/config.py index be6f382a..68abf484 100644 --- a/silk/config.py +++ b/silk/config.py @@ -28,6 +28,7 @@ class SilkyConfig(six.with_metaclass(Singleton, object)): 'SILKY_INTERCEPT_PERCENT': 100, 'SILKY_INTERCEPT_FUNC': None, 'SILKY_PYTHON_PROFILER': False, + 'SILKY_STORAGE_CLASS': 'silk.storage.ProfilerResultStorage' } def _setup(self): diff --git a/silk/migrations/0004_request_prof_file_storage.py b/silk/migrations/0004_request_prof_file_storage.py index 918e26aa..e780e849 100644 --- a/silk/migrations/0004_request_prof_file_storage.py +++ b/silk/migrations/0004_request_prof_file_storage.py @@ -16,6 +16,6 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='request', name='prof_file', - field=models.FileField(null=True, storage=silk.models.ProfilerResultStorage(), upload_to=''), + field=models.FileField(null=True, storage=silk.models.silk_storage, upload_to=''), ), ] diff --git a/silk/migrations/0005_increase_request_prof_file_length.py b/silk/migrations/0005_increase_request_prof_file_length.py index a480fd44..7465b0dd 100644 --- a/silk/migrations/0005_increase_request_prof_file_length.py +++ b/silk/migrations/0005_increase_request_prof_file_length.py @@ -16,6 +16,6 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='request', name='prof_file', - field=models.FileField(max_length=300, null=True, storage=silk.models.ProfilerResultStorage(), upload_to=''), + field=models.FileField(max_length=300, null=True, storage=silk.models.silk_storage, upload_to=''), ), ] diff --git a/silk/models.py b/silk/models.py index e1ef3daf..b31d8cbd 100644 --- a/silk/models.py +++ b/silk/models.py @@ -4,7 +4,7 @@ import random import re -from django.core.files.storage import FileSystemStorage +from django.core.files.storage import get_storage_class from django.db import models from django.db.models import ( DateTimeField, TextField, CharField, ForeignKey, IntegerField, @@ -23,6 +23,8 @@ # Django 1.8 removes commit_on_success, django 1.5 does not have atomic atomic = getattr(transaction, 'atomic', None) or getattr(transaction, 'commit_on_success') +silk_storage = get_storage_class(SilkyConfig().SILKY_STORAGE_CLASS)() + # Seperated out so can use in tests w/o models def _time_taken(start_time, end_time): @@ -53,16 +55,6 @@ def __init__(self, d): self[k] = v -class ProfilerResultStorage(FileSystemStorage): - # the default storage will only store under MEDIA_ROOT, so we must define our own. - def __init__(self): - super(ProfilerResultStorage, self).__init__( - location=SilkyConfig().SILKY_PYTHON_PROFILER_RESULT_PATH, - base_url='' - ) - self.base_url = None - - class Request(models.Model): id = CharField(max_length=36, default=uuid4, primary_key=True) path = CharField(max_length=190, db_index=True) @@ -82,9 +74,7 @@ class Request(models.Model): meta_num_queries = IntegerField(null=True, blank=True) meta_time_spent_queries = FloatField(null=True, blank=True) pyprofile = TextField(blank=True, default='') - prof_file = FileField( - max_length=300, null=True, storage=ProfilerResultStorage() - ) + prof_file = FileField(max_length=300, null=True, storage=silk_storage) @property def total_meta_time(self): diff --git a/silk/storage.py b/silk/storage.py new file mode 100644 index 00000000..34291724 --- /dev/null +++ b/silk/storage.py @@ -0,0 +1,13 @@ +from django.core.files.storage import FileSystemStorage + +from silk.config import SilkyConfig + + +class ProfilerResultStorage(FileSystemStorage): + # the default storage will only store under MEDIA_ROOT, so we must define our own. + def __init__(self): + super(ProfilerResultStorage, self).__init__( + location=SilkyConfig().SILKY_PYTHON_PROFILER_RESULT_PATH, + base_url='' + ) + self.base_url = None