Webアプリケーションの監視にPythonエージェントを最大限に活用するために、いくつかのヒントをご紹介します。
デコレーターと内観
トランザクションや関数のトレースノードに名前を付けるとき、Pythonエージェントは呼び出される関数の名前を調べる必要があります。関数が生の関数やクラスメソッドである場合、これはすべてうまくいきます。しかし、関数やクラスメソッドにデコレーターが適用されている場合、もしデコレーターがラップされた関数のイントロスペクト機能を維持するように実装されていなければ、エージェントはラップされた関数の代わりにデコレーターのラッパー関数の名前を使用します。
デコレーターの典型的な実装方法は、パターンを使用することです。
def decorator(f): def _decorator(): f() return _decorator
@decoratordef foo(): pass
この実装の問題は、 foo.__name__
の値を見ると、それがfoo
_decorator
になることです。デコレータが別のモジュールに含まれている場合、 foo.__module__
を見ると、デコレータが宣言されているモジュールの名前になり、ラップされた関数が含まれているモジュールの名前にはなりません。
モジュールと関数の名前が正しく付けられるようにするには、標準ライブラリfunctoolsモジュールのwraps()
デコレータを使用して、内部のデコレータ関数をラップします。
import functools
def decorator(f): @functools.wraps(f) def _decorator(): f() return _decorator
@decoratordef foo(): pass
詳細については、Python Web サイトでwraps()
関数のドキュメントを参照してください。
トランザクションの識別
Python エージェントがトランザクションのエラーの詳細を記録したり、スローなトランザクションのトレースをキャプチャしたりするとき、そのトランザクションに対して個別に記録した他のデータと関連付けるために使用できる固有の識別子がありません。これは、例えば、UIからの情報と自分のウェブアプリケーションのログを一致させることを困難にしています。
このようなクロスマッチングを実行できるようにしたい場合、または単にトランザクションに対してこの状況で役立つ可能性のある追加の詳細をキャプチャしたい場合は、エージェントAPIを使用して、トランザクションに対してカスタム 引数を記録できます。 エラーが発生した場合、または低速の トレースが記録されてUIに表示される場合、指定したこれらの追加の引数は、エラーまたはトレースの詳細の Custom parameters セクションの下に表示されます。
このような追加の詳細を追加するには、 newrelic.agentモジュールのadd_custom_attribute()
関数を使用できます。
重要
トランザクション名の末尾に括弧[suffix]
を使用しないでください。エージェントは名前から括弧を自動的に削除します。代わりに、必要に応じて括弧(suffix)
またはその他の記号を使用してください。
例えば、Django web framework チュートリアルの polls アプリケーションのコードを見てみましょう。
from django.shortcuts import render_to_response, get_object_or_404
def detail(request, poll_id): p = get_object_or_404(Poll, pk=poll_id) return render_to_response('polls/detail.html', {'poll': p})
もし、問題が発生したときに利用できるように、トランザクションに対してポールIDを記録したい場合は、次のようにします。
import newrelic.agent
def detail(request, poll_id): newrelic.agent.add_custom_attribute('poll_id', poll_id) p = get_object_or_404(Poll, pk=poll_id) return render_to_response('polls/detail.html', {'poll': p})
カスタム引数に使用される値は、 jsonモジュールによって提供される JSON エンコーダーによってシリアル化できる任意の値にすることができます。 これにはタプル、リスト、辞書が含まれます。
推奨事項: 値を整数、フロート、または文字列値に制限します。 より複雑なデータ構造を使用する場合は、収集され、パッケージ化されてからコア アプリケーションに送信されるまでキャッシュする必要があるため、大きすぎるデータ構造を関連付けないようにしてください。
また、値がJSONにシリアライズできない場合、エラーの詳細や遅いトランザクションが捨てられてしまう可能性があるため、シンプルな値が望ましいです。
カスタムメトリクスの記録
我々は、我々が知っている公的に利用可能なPythonのサードパーティモジュールのみをインスツルメンテーションすることができます。あなた自身のコードのためにインストルメンテーションを拡張するには、 adding Python instrumentation で説明されているテクニックを使用してください。これにより、ウェブトランザクションのパフォーマンスブレークダウンデータや低速トランザクションのトレースをカバーすることができます。
API 呼び出しを介して任意のパフォーマンス データを記録できます (例: タイミングまたはコンピューター リソース データ)。次に、メトリクスとイベントを使用してグラフを作成し、そのメトリクスを追跡します。カスタム メトリックを使用して、監視を統合できます。
カスタムメトリックを記録するには、 newrelic.agentモジュールのrecord_custom_metric()
関数を使用します。 メトリクスの名前と値の 2 つの引数を取ります。 値は整数または浮動小数点値である必要があります。
import newrelic.agent
def create_account(request, ...): ... newrelic.agent.record_custom_metric('Custom/Signups', 1) ... return render_to_response('...', ...)
メトリック名Custom/
のパスを開始して、既存のエージェント メトリック ( Custom/MyMetric
など) との名前空間の競合を回避します。
カスタム メトリックは、収集サイクルごとに集計され、コレクターに送信されます。この場合、各1
が加算されて、収穫サイクルのサインアップ数が記録されます。
関数トレース機能は、関数呼び出しやコードブロック内の時間を追跡するために使用されますが、個別のカスタムチャートを作成することはできません。カスタムメトリクスを使用して、何かにかかった時間を記録し、チャートにすることはできます。
これを容易にするために、メトリックのタイミングと記録のためのコンテキスト・マネージャー・クラスを事前に定義することができます。
class CustomMetricTimedNode(object):
def __init__(self, name): self.name = name self.start_time = None self.end_time = None
def __enter__(self): self.start_time = time.time() return self
def __exit__(self, exc, value, tb): if not self.start_time: return self.end_time = time.time() duration = self.end_time - self.start_time newrelic.agent.record_custom_metric(self.name, duration)
これは、コード ブロックを囲むwith
ステートメントと組み合わせて使用できます。
def function(): with CustomMetricTimedNode('Custom/TimedNode1'): time.sleep(0.01)
このコンテキストマネージャーを関数に適用するには、関数デコレーターを作成します。
def custom_metric_timed_node(name): def _decorator(f): @functools.wraps(f) def _wrapper(*args, **kwargs): with CustomMetricTimedNode(name): return f(*args, **kwargs) return _wrapper return _decorator
として使用されていると。
@custom_metric_timed_node('Custom/TimedNode2')def function(): time.sleep(0.01)
関数トレースのためにインスツルメンテーションを追加する場合と同様に、メトリック名は有限のセット内で、比較的小さな長さのものを選ぶことをお勧めします。値に制限のない名前は避けるべきです。そうしないと、大量の名前を意味のある形で表示することが難しくなります。また、ユニークな名前が多いと、メモリが過剰に使用され、エージェントが名前を強制的に正規化して、ユニークな名前の数を制限することになります。
注意
あまりにも多くのメトリクスを収集すると、アプリケーションとエージェントの両方のパフォーマンスに影響を与える可能性があります。潜在的なデータの問題を回避するために、カスタムインスツルメンテーションによって導入されるユニークなメトリクスの総数を2000以下に抑えるようにしてください。