Go エージェントのコードレベルのメトリック設定の手順を使用してコードレベルのメトリックを有効にした後、追加のインストルメンテーションを使用してメトリックの収集方法を微調整できます。
トランザクションの計測
コードレベルのメトリクスを有効にすると、Go エージェントは、アプリケーションのStartTransactionメソッドの呼び出しによって開始されたすべてのトランザクションにソース コード コンテキスト情報を追加します。既存のインストルメンテーション コードを変更することなく、これはStartTransactionを呼び出した関数に基づいてソース コードの場所が追加されることを意味します。これは、計測パッケージによってStartTransactionが呼び出された場合でも当てはまります。
ただし、特定のトランザクションのコード レベルの指標を収集する方法を手動で制御したい場合は、以下に示すように、いくつかのnewrelic.TraceOption関数を追加できます。
単一トランザクションのコード レベル メトリックの抑制
特定のトランザクションのコード レベルのメトリックが必要ない場合 (たとえば、そのデータが必要ないことがわかっているときに情報を収集するオーバーヘッドを回避するため)、 WithoutCodeLevelMetrics 呼び出しの最後に StartTransaction 関数を追加します。
txn := app.StartTransaction("nothing-here-to-see", newrelic.WithoutCodeLevelMetrics())defer txn.End()ファイル パスのプレフィックスの調整
デフォルトでは、Go エージェントは、コードレベルのメトリクスによって参照されるソース ファイルの完全な (絶対) ファイル パス名を報告します。構成ガイドには、ファイル パス名をグローバルに切り捨てて、 ConfigCodeLevelMetricsPathPrefixes設定を介して選択したディレクトリ名から開始する方法に関する情報が記載されていますが、個々のトランザクションに対して異なるファイル パス名プレフィックスを指定する必要がある場合があります。その場合は、トランザクションにWithPathPrefixesオプションを追加してください:
txn := app.StartTransaction("mytransaction", newrelic.WithPathPrefixes("otherproject/lib/src"))defer txn.End()これは、このトランザクションの場合のみ、たとえば"/usr/src/otherproject/lib/src/main.go"のソース ファイル パス名が"otherproject/lib/src/main.go"に短縮されることを意味します。
使用したいパス接頭辞が複数ある場合は、それらを追加パラメータとしてWithPathPrefixesに渡すだけです:
txn := app.StartTransaction("mytransaction", newrelic.WithPathPrefixes("otherproject/lib/src", "myproject/src"))defer txn.End()関数認識ヒューリスティックの無視プレフィックスの調整
デフォルトでは、Go エージェントには、インスツルメントしている関数に到達するために、エージェント自体の内部にあるコール スタック内の関数をスキップするロジックが含まれています。構成ガイドには、 ConfigCodeLevelMetricsIgnoredPrefixes設定を介してこのヒューリスティックをグローバルに変更する方法に関する情報が記載されていますが、単一のトランザクションに対してカスタムの名前空間無視プレフィックスを提供したい場合があります。これを行うには、トランザクションにWithIgnoredPrefixesオプションを追加します:
txn := app.StartTransaction("mytransaction", newrelic.WithIgnoredPrefixes("github.com/ignore/this/"))defer txn.End()関数を無視するパッケージが複数ある場合は、 WithIgnoredPrefixesに複数の文字列引数を指定できます。
txn := app.StartTransaction("mytransaction", newrelic.WithIgnoredPrefixes("github.com/ignore/this/", "github.com/ignore/that/"))defer txn.End()この変更により、名前がgithub.com/ignore/this/ (または 2 番目の例ではgithub.com/ignore/that/ ) で始まるパッケージの関数はすべてスキップされ、インストルメント化されている関数が検索されます。
コードの場所を明示的にマークする
レポート対象のポイントを簡単に識別できるようにするには、 StartTransaction呼び出しの末尾にWithThisCodeLocationを追加します (たとえば、トランザクションが実際に別のフレームワーク内で開始される場合)。これにより、コード レベルのメトリックは、 WithThisCodeLocationが呼び出されたソース コード内の場所をレポートするようになります。
txn := app.StartTransaction("mytransaction", newrelic.WithThisCodeLocation())defer txn.End()コードの場所を明示的にマークする
また、トランザクションに関連付けるソース コード内の場所を完全に制御することもできます。基本的に、 ThisCodeLocationを呼び出してその場所の「マーカー」を取得することで、任意の場所をマークできます。次に、その保存されたマーカーをWithCodeLocationオプションでStartTransaction呼び出しに使用します。
here := newrelic.ThisCodeLocation()...txn := app.StartTransaction("mytransaction", newrelic.WithCodeLocation(here))defer txn.End()必要に応じて、 ThisCodeLocationにいくつかの呼び出し関数をスキップするように指示して、報告された場所がコール スタックのさらに上になるようにすることができます。たとえば、1 つの呼び出し元をスキップして、 hereがThisCodeLocationを呼び出す関数の呼び出し元を参照するようにするには、上記の例を次のように変更します。
here := newrelic.ThisCodeLocation(1)...txn := app.StartTransaction("mytransaction", newrelic.WithCodeLocation(here))defer txn.End()関数値に基づいてコードの場所を明示的にマークする
計測するコードが、関数の名前や関数リテラル値などのfunc型の値として利用できる場合、 WithFunctionLocationオプションをStartTransactionに追加し、 func値をパラメーターとして渡します。
func myfunction() { ... }...txn := app.StartTransaction("myfunction", newrelic.WithFunctionLocation(myfunction))または
someFunction := func() {...}...txn := app.StartTransaction("myfunction", newrelic.WithFunctionLocation(someFunction))後でWithCodeLocationオプションで使用するために、 func値からCodeLocation値を取得することもできます。これを、後でWithCodeLocationで参照できるようにThisCodeLocationでコードの場所を保存する上記の使用法と比較してください。今回は同じことを行いますが、代わりにfunc値を使用します。
func myFunc() {...}...locationOfMyFunc, err := newrelic.FunctionLocation(myFunc)if err != nil { // handle the case that the location could not be determined // from the value passed to FunctionLocation.}...txn := app.StartTransaction("mytransaction", newrelic.WithCodeLocation(locationOfMyFunc))FunctionLocation は、渡された値が有効な関数でない場合、またはソース コードの場所を取得できなかった場合にエラーを返すことに注意してください。対照的に、 WithFunctionLocation オプションは、可能であれば渡された値に基づいてコードレベルのメトリックを設定しますが、エラーが発生した場合は何もしません。
ラップされたハンドラーへのカスタム オプションの追加
StartTransactionの末尾に追加できる上記と同じオプションをWrapHandleとWrapHandleFuncに追加して、必要に応じて、それらによって開始されたトランザクションに関連付けられたコードレベルのメトリック コレクションを調整することもできます (ただし、ほとんどの場合WrapHandleおよびWrapHandleFunc関数は、インストルメント化されているコードの場所を正しく識別します)。例えば:
http.HandleFunc(newrelic.WrapHandleFunc(app, "/endpoint", endpointFunction, newrelic.WithThisCodeLocation()))トランザクション開始後のトレース オプションの変更
場合によっては、トランザクションが既に開始されるまでコードの場所を知る余裕がない場合があります (おそらくフレームワークまたは統合機能によって)。SetOptionメソッドを呼び出すことで、既存のトランザクションのトランザクション オプションを変更できます。パラメーターは、上で説明したようにTraceOption関数のセットです。例えば:
txn := newrelic.FromContext(r.context)txn.SetOption(newrelic.WithThisCodeLocation())キャッシュされたコードレベルのメトリクス関数によるパフォーマンスの向上
多くの場合、コード レベルのメトリクスでトランザクションをインストルメント化する最も便利な方法は、インストルメント化された関数内でnewrelic.WithThisCodeLocation() (または上記の同様の関数) を呼び出すことです。ただし、その関数がアプリケーションの実行中に何度も呼び出される場合は、ソース コードの場所を繰り返し計算するオーバーヘッドを回避することをお勧めします。これは、トランザクション コードが多くのゴルーチンで同時に実行される場合に特に当てはまります。
これを軽減するために、Go エージェントはこれらの関数のいくつかのキャッシュバージョンを提供します。それらは、最初に呼び出されたときにソースコードの場所を特定する作業のみを行い、その後はその値を再利用するだけであることを除いて、キャッシュされていない対応するものと同じように動作します。
この機能を利用するには、 NewCachedCodeLocation()を呼び出してキャッシュ ストレージ変数を作成し、計測されたトランザクションの実行間で保持される場所に配置する必要があります。この変数は、そのコードの場所のキャッシュされた値を保持します。次に、同じ名前のスタンドアロン関数を使用するのと同じように、メソッドFunctionLocation(functionValue)またはThisCodeLocation()を使用しますが、この場合、それらはCachedCodeLocation変数のメソッドです。これらのメソッドはスレッドセーフであるため、追加の同時実行制御を追加しなくても、並行ゴルーチンで使用できます。
たとえば、このコードでは、 myFunc変数に割り当てられたクロージャで使用されるキャッシュ変数を設定しています。
cache := newrelic.NewCachedCodeLocation()
myFunc := func() { txn := app.StartTransaction("mytransaction", cache.WithThisCodeLocation()) defer txn.End() // go on to perform the transaction}(この例では、 appがエージェントの開始時に作成されたエージェントのApplication値であり、このコード スニペットに表示されると想定しています。)
これで、 myFunc関数を何度も呼び出すことができます。myFuncの各 (場合によっては同時の) 呼び出しには、 cache変数への参照があります。cache.WithThisCodeLocation()を実行する最初の呼び出しは、その時点でのソース コードの場所を計算し、それをcache変数に格納します。myFuncの後続の実行では、以前にcacheに格納された値が再利用されます。
ポイントは、その場所を一度だけ評価し、そこからキャッシュされた値を使用することであるため、使用するコードの場所ごとに異なるキャッシュ変数を使用する必要があることに注意してください。キャッシュ変数は、ここおよびモジュール パッケージのドキュメントに記載されている以外にコピーまたは使用することを意図していません。
使用できるすべてのキャッシュされたコードレベルのメトリクス関数とメソッドの詳細については、Go モジュール パッケージの完全なドキュメント を参照してください。