Skip to content

Commit

Permalink
configurable storage class (#204)
Browse files Browse the repository at this point in the history
* move ProfilerResultStorage to own module to resolve import

* use SilkyConfig for SILKY_STORAGE_CLASS

* terse storage definition

* didn't mean to reorder imports

* increase Request.prof_file max_length to 300 (#203)

* test default storage class
  • Loading branch information
smcoll authored and avelis committed Aug 8, 2017
1 parent bdf2cdb commit 688f409
Show file tree
Hide file tree
Showing 7 changed files with 33 additions and 17 deletions.
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,14 @@ When enabled a graph visualisation generated using [gprof2dot](https://github.co

<img src="https://raw.githubusercontent.com/jazzband/silk/master/screenshots/10.png" width="720px"/>

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.
Expand Down
5 changes: 5 additions & 0 deletions project/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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):

Expand Down
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(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):
Expand Down
2 changes: 1 addition & 1 deletion silk/migrations/0004_request_prof_file_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -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=''),
),
]
2 changes: 1 addition & 1 deletion silk/migrations/0005_increase_request_prof_file_length.py
Original file line number Diff line number Diff line change
Expand Up @@ -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=''),
),
]
18 changes: 4 additions & 14 deletions silk/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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):
Expand Down Expand Up @@ -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)
Expand All @@ -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):
Expand Down
13 changes: 13 additions & 0 deletions silk/storage.py
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 688f409

Please sign in to comment.