GitHubじゃ!Pythonじゃ!

GitHubからPython関係の優良リポジトリを探したかったのじゃー、でも英語は出来ないから日本語で読むのじゃー、英語社会世知辛いのじゃー

jazzband

django-silk – Djangoの滑らかで滑らかなプロファイリング

投稿日:

Djangoの滑らかで滑らかなプロファイリング

シルク

Silkは現在Jazzbandの組織に移り、貢献者を募集しています。あなたが手伝ってくれると思ったら、お気軽にお問い合わせください!

Silkは、Djangoフレームワークのためのライブプロファイリングとインスペクションツールです。 SilkはHTTPリクエストとデータベースクエリをインターセプトしてユーザインタフェースに提示してからさらに検査します:

内容

要件

シルクは以下のテストを受けました:

  • Django:1.11,2.0
  • Python:2.7,3.4,3.5,3.6

インストール

virtualenvにpipを通して:

pip install django-silk

settings.pyに以下を追加してください:

MIDDLEWARE = [
    ...
    'silk.middleware.SilkyMiddleware',
    ...
]

INSTALLED_APPS = (
    ...
    'silk'
)

注:ミドルウェアの配置は機密です。 ミドルウェアがsilk.middleware.SilkyMiddleware前にprocess_requestから戻ってきたら、 SilkyMiddlewareは決して実行する機会を得られません。 したがって、前に配置されたミドルウェアがprocess_requestから何も返さないようにする必要があります。 詳細については、 djangoのドキュメントを参照してください。

注意: django.middleware.gzip.GZipMiddlewareを使用している場合は、 django.middleware.gzip.GZipMiddleware 前に silk.middleware.SilkyMiddlewareます。そうしないと、エンコーディングエラーが発生します。

ユーザーインターフェイスへのアクセスを有効にするには、 urls.py次の行を追加します。

urlpatterns += [url(r'^silk/', include('silk.urls', namespace='silk'))]

移行を実行する前に:

python manage.py makemigrations

python manage.py migrate

python manage.py collectstatic

Silkは自動的にリクエストの傍受を開始し、必要に応じてプロファイリングを追加することができます。 UIは、 /silk/

代替インストール

githubタグ経由:

pip install https://github.com/jazzband/silk/archive/<version>.tar.gz

以下を使用してmasterからインストールできますが、masterのバージョンが要件で指定されているすべてのバージョンで動作していない可能性があることに注意してください

pip install -e git+https://github.com/jazzband/django-silk.git#egg=silk

特徴

シルクは主に次のもので構成されます。

  • リクエスト/レスポンスをインターセプトするためのミドルウェア
  • データベースクエリのプロファイリングのためのSQL実行に関するラッパー
  • コードや関数のブロックを手動または動的にプロファイリングするためのコンテキストマネージャ/デコレータ。
  • 上記の検査と視覚化のためのユーザーインターフェース。

検査依頼

Silkミドルウェアは、構成されたデータベース内の要求と応答を傍受して格納します。 これらのリクエストは、リクエストの概要を通してSilkのUIを使用してフィルタリングして検査することができます。

それは次のようなものを記録します:

  • 撮影時間
  • Num。 クエリ
  • クエリに費やされた時間
  • リクエスト/レスポンスヘッダ
  • リクエスト/レスポンス団体

等々。

関連するリクエストをクリックすると、各リクエストの詳細が表示されます。

SQL検査

Silkはまた、各要求によって生成されるSQLクエリをインターセプトします。 関係するテーブル、ジョイン数、実行時間などの要約を得ることができます(テーブルは列ヘッダをクリックすることでソートできます):

このリクエストがどこから来たのかを知るためにスタックトレースに入る前に:

プロファイリング

Pythonの組み込みcProfileプロファイラを使用するには、SILKY_PYTHON_PROFILER設定をオンにします。 各リクエストは個別にプロファイリングされ、プロファイラの出力はSilk UIのリクエストのプロファイリングページで利用可能になります。

SILKY_PYTHON_PROFILER = True

バイナリ.profファイルも生成したい場合は、次のように設定します。

SILKY_PYTHON_PROFILER_BINARY = True

有効にすると、 gprof2dotおよびviz.jsを使用して生成されたグラフの視覚化がプロファイルの詳細ページに表示されます。

保存された生成されたバイナリ.profファイルにカスタムストレージクラスを使用できます。

SILKY_STORAGE_CLASS = 'path.to.StorageClass'

デフォルトのストレージクラスはsilk.storage.ProfilerResultStorageです。これを使用する場合は、選択したパスを指定できます。 指定されたディレクトリが存在することを確認する必要があります。

# If this is not set, MEDIA_ROOT will be used.
SILKY_PYTHON_PROFILER_RESULT_PATH = '/path/to/profiles/'

ダウンロードボタンは、リクエストごとにバイナリの.profファイルで利用できるようになります。 このファイルは、 snakevizやその他のcProfileツールを使用してさらに解析するために使用できます

Silkは、コード/関数の特定のブロックのプロファイリングにも使用できます。 これは、この目的のためにデコレータとコンテキストマネージャを提供します。

例えば:

from silk.profiling.profiler import silk_profile


@silk_profile(name='View Blog Post')
def post(request, post_id):
    p = Post.objects.get(pk=post_id)
    return render_to_response('post.html', {
        'post': p
    })

ブログ投稿が表示されるたびに、Silk UI内にエントリが表示されます。

シルクプロファイリングは、実行時間を提供するだけでなく、要求と同じ方法でブロック内で実行されるSQLクエリを収集します。

デコレータ

シルクデコレータは、関数とメソッドの両方に適用できます

from silk.profiling.profiler import silk_profile


# Profile a view function
@silk_profile(name='View Blog Post')
def post(request, post_id):
    p = Post.objects.get(pk=post_id)
    return render_to_response('post.html', {
        'post': p
    })


# Profile a method in a view class
class MyView(View):
    @silk_profile(name='View Blog Post')
    def get(self, request):
        p = Post.objects.get(pk=post_id)
        return render_to_response('post.html', {
            'post': p
        })

コンテキストマネージャ

コンテキストマネージャを使用すると、名前にコンテキストを追加することができます。これにより、特定のデータベースレコードの処理速度を絞り込むのに役立ちます。

def post(request, post_id):
    with silk_profile(name='View Blog Post #%d' % self.pk):
        p = Post.objects.get(pk=post_id)
        return render_to_response('post.html', {
            'post': p
        })

動的プロファイリング

Silkの興味深い機能の1つに、動的プロファイリングがあります。 たとえば、読み取り専用アクセスしか持たない依存関係の関数(例えば、システム所有のpythonライブラリがrootによって所有されている)をプロファイリングしたい場合、実行時にデコレータを適用するためにsettings.pyに以下を追加することができます:

SILKY_DYNAMIC_PROFILING = [{
    'module': 'path.to.module',
    'function': 'MyClass.bar'
}]

これは、

class MyClass(object):
    @silk_profile()
    def bar(self):
        pass

以下にその可能性を要約します。

"""
Dynamic function decorator
"""

SILKY_DYNAMIC_PROFILING = [{
    'module': 'path.to.module',
    'function': 'foo'
}]

# ... is roughly equivalent to
@silk_profile()
def foo():
    pass

"""
Dynamic method decorator
"""

SILKY_DYNAMIC_PROFILING = [{
    'module': 'path.to.module',
    'function': 'MyClass.bar'
}]

# ... is roughly equivalent to
class MyClass(object):

    @silk_profile()
    def bar(self):
        pass

"""
Dynamic code block profiling
"""

SILKY_DYNAMIC_PROFILING = [{
    'module': 'path.to.module',
    'function': 'foo',
    # Line numbers are relative to the function as opposed to the file in which it resides
    'start_line': 1,
    'end_line': 2,
    'name': 'Slow Foo'
}]

# ... is roughly equivalent to
def foo():
    with silk_profile(name='Slow Foo'):
        print (1)
        print (2)
    print(3)
    print(4)

動的プロファイリングは、関数をインプレースで変更する点で、Pythonモックフレームワークと同様に動作することに注意してください。

""" my.module """
from another.module import foo

# ...do some stuff
foo()
# ...do some other stuff

my.module.fooとは対照的に、 my.module.fooを動的にmy.module.fooすることによってfooをプロファイルします。

SILKY_DYNAMIC_PROFILING = [{
    'module': 'my.module',
    'function': 'foo'
}]

すでにインポートされたに、関数ソースモジュールanother.module.foo 動的プロファイルを適用すると、プロファイリングはトリガーされません。

コード生成

Silkは現在、要求ごとに2ビットのコードを生成しています。

どちらも要求の再生に使用することを意図しています。 curlコマンドはコマンドライン経由で再生することができ、PythonコードはDjangoユニットテスト内で使用することも、単なるスタンドアロンスクリプトとして使用することもできます。

構成

認証/承認

デフォルトでは、誰でもSilkのユーザーインターフェイスにアクセスするには、 /silk/ます。 Djangoの認証バックエンドを有効にするには、 settings.py次のように記述しsettings.py

SILKY_AUTHENTICATION = True  # User must login
SILKY_AUTHORISATION = True  # User must have permissions

SILKY_AUTHORISATIONTrue場合、デフォルトでSilkはis_staff属性がTrue設定されているユーザーのみを認証します。

これをカスタマイズするには、 settings.py次のようにしsettings.py

def my_custom_perms(user):
    return user.is_allowed_to_use_silk

SILKY_PERMISSIONS = my_custom_perms

lambda使用することもできます。

SILKY_PERMISSIONS = lambda user: user.is_superuser

リクエスト/レスポンス団体

デフォルトでは、Silkは要求の度にリクエストとレスポンスのボディを保存します。 Silkが大きなボディで大量生産されている場合、これはスペース/時間パフォーマンスに大きな影響を与えます。 この動作は、次のオプションを使用して構成できます。

SILKY_MAX_REQUEST_BODY_SIZE = -1  # Silk takes anything <0 as no limit
SILKY_MAX_RESPONSE_BODY_SIZE = 1024  # If response body>1024kb, ignore

メタプロファイリング

Silkが要求/応答時間にどのような影響を与えているかを見ることができると便利なことがあります。 これを行うには、 settings.py次の行を追加しsettings.py

SILKY_META = True

Silkは次に、各要求の最後にすべてをデータベースに保存するまでの時間を記録します。

上記のスクリーンショットでは、リクエストが29ms(Djangoから22ms、Silkから7ms)かかることに注意してください。

要求の一部を記録する

高負荷のサイトでは、作成された要求のほんの一部を記録するのが役に立ちます。これを行うには、 settings.py次の行を追加しsettings.py

注:この設定はSILKY_INTERCEPT_FUNCと相互排他的です。

SILKY_INTERCEPT_PERCENT = 50 # log only 50% of requests

要求を記録するためのカスタムロジック

高負荷のサイトでは、リクエストを傍受するための独自のロジックを記述することも役立ちます。これを行うには、 settings.py次の行を追加しsettings.py

注:この設定はSILKY_INTERCEPT_PERCENTと相互排他的です。

def my_custom_logic(request):
    return 'record_requests' in request.session

SILKY_INTERCEPT_FUNC = my_custom_logic # log only session has recording enabled.

lambda使用することもできます。

# log only session has recording enabled.
SILKY_INTERCEPT_FUNC = lambda request: 'record_requests' in request.session

要求/応答データの制限

シルキーなゴミが古いリクエスト/レスポンスデータを収集するためには、config varを設定して、それが格納するリクエスト/レスポンスの行数を制限することができます。

SILKY_MAX_RECORDED_REQUESTS = 10**4

ガベージコレクションは、オーバーヘッドを削減する要求の割合に対してのみ実行されます。 この設定で調整することができます:

SILKY_MAX_RECORDED_REQUESTS_CHECK_PERCENT = 10

ログデータの消去

管理コマンドは、ログに記録されたすべてのデータを消去します。

python manage.py silk_clear_request_log

貢献する

これはジャズバンドプロジェクトです。 貢献することにより、あなたはコントリビュータ行動規範を遵守し、 ガイドラインに従うことに同意します。

開発環境

Silkには、 silk開発に使用できるプロジェクトという名前のprojectがあります。 シンクコードがシンボリックリンクされているので、サンプルprojectsilkパッケージで同時に作業できます。

ローカル開発をセットアップするには、最初にテストprojectすべての依存関係をインストールする必要があります。 projectディレクトリのルートから:

pip install -r test-requirements.txt

また、 silkの依存関係をインストールする必要があります。 gitリポジトリのルートから:

pip install -r requirements.txt

この時点で、仮想環境には、サンプルprojectsilk両方を正常に実行するために必要なものすべてが必要です。

実行する前に、 DBおよびDB_NAME環境変数を設定する必要があります。

export DB=sqlite3
export DB_NAME=db.sqlite3

他の組み合わせについては、 .travis.ymlチェックして.travis.yml

サンプルprojectディレクトリのルートから、djangoサーバを起動します。

python manage.py runserver

テストの実行

cd project
./tests/test_migrations.sh
python manage.py test --noinput

ハッピープロファイリング!







-jazzband

執筆者: