すべてのプロダクト
Search
ドキュメントセンター

Application Real-Time Monitoring Service:Go エージェントのカスタム拡張の使用

最終更新日:Jun 23, 2026

Go 向けの Application Real-Time Monitoring (ARMS) エージェントは、ソースコードを変更することなくカスタム機能を挿入できるカスタム拡張を提供します。これにより、リクエストパラメーターやリクエストボディからデータをキャプチャして問題のトラブルシューティングに役立てることができます。このトピックでは、Net/HTTP を例に、これらの拡張機能を使用してリクエストヘッダーとレスポンスヘッダーをキャプチャする方法を説明します。

前提条件

  • アプリケーションが Go 1.18 以降で実行されていること。

  • Go アプリケーションが Application Real-Time Monitoring (ARMS) と統合されていること。

    重要

    統合ドキュメントで指定されているように、ビルドコマンドを ./instgo go build xxx に変更してください。

制限事項

  • カスタム拡張を使用して package main 内のユーザー定義関数を計装することはできません。

  • カスタム拡張を使用して、レシーバータイプが any である関数を計装することはできません。

コードの仕様

  • フックコードで package main を使用しないでください。

  • バージョン 2.0.0 以降のコードを使用する場合、次のように import 文に "_ unsafe" を追加する必要があります。

    import (
    	"encoding/json"
    	"fmt"
    	"github.com/alibaba/loongsuite-go-agent/pkg/api"
    	"net/http"
            _ "unsafe"
    )
  • OnEnter 関数の最初のパラメーターは常に call api.CallContext で、2 番目のパラメーターは ReceiverType (存在する場合)、それ以降のパラメーターは挿入された関数のリクエストパラメーターです。

    説明

    ReceiverType* が含まれる場合、文字をエスケープするには、JSON ファイルに \\ プレフィックスを追加する必要があります。

  • OnExit 関数の最初のパラメーターは call api.CallContext として固定されており、後続のパラメーターは、挿入された関数の戻り値が順番に指定されます。

例えば、net/http::(*Transport).RoundTrip 関数は以下の通りです。

func (t *Transport) RoundTrip(req *Request) (*Response, error) {
	return t.roundTrip(req)
}

RoundTrip の ReceiverType は *Transport であるため、OnEnter 関数の 2 番目のパラメーターは *Transport、3 番目のパラメーターは req *Request になります。OnExit 関数の 2 番目と 3 番目のパラメーターは、RoundTrip の戻り値である *Response, error です。

ReceiverType がエクスポートされていない型である場合、_ interface{} を代わりとして使用できます。また、無視したいパラメーターがある場合も、_ interface{} を代わりとして使用できます。

操作手順

  1. 現在のプロジェクト外のディレクトリに、rules という名前のフォルダーを作成し、go mod init rules コマンドを実行して初期化してから、そのフォルダーに以下のコードで rules.go という名前のファイルを作成します。

    このコードはカスタム拡張を定義します。

    package rules
    import (
    	"encoding/json"
    	"fmt"
    	"github.com/alibaba/loongsuite-go-agent/pkg/api"
    	"net/http"
            _ "unsafe"
    )
    //go:linkname httpClientEnterHook1 net/http.httpClientEnterHook1
    func httpClientEnterHook1(call api.CallContext, t *http.Transport, req *http.Request) {
    	header, _ := json.Marshal(req.Header)
    	fmt.Println("request header is ", string(header))
    }
    //go:linkname httpClientExitHook1 net/http.httpClientExitHook1
    func httpClientExitHook1(call api.CallContext, res *http.Response, err error) {
    	header, _ := json.Marshal(res.Header)
    	fmt.Println("response header is ", string(header))
    }
  2. config.json ファイルを修正し、以下の内容を追加してフックコードを net/http::(*Transport).RoundTrip にインジェクトします。

    [
      {
        "ImportPath":"net/http",
        "Function":"RoundTrip",
        "OnEnter":"httpClientEnterHook1",
        "ReceiverType": "\\*Transport",
        "OnExit": "httpClientExitHook1",
        "Path": "/extension/rules" // rules フォルダーへの絶対パスに置き換えます。
      }
    ]
  3. テストデモを作成します。

    rules フォルダー以外のディレクトリに、デモアプリケーション用のフォルダーを作成し、go mod init demo コマンドを使用して初期化します。次に、demo フォルダーに、以下のコードを含む net_http.go ファイルを作成します。

    package main
    import (
    	"context"
    	"net/http"
    )
    func main() {
    	req, err := http.NewRequestWithContext(context.Background(), "GET", "http://www.baidu.com", nil)
    	if err != nil {
    		panic(err)
    	}
    	req.Header.Set("otelbuild", "true")
    	client := &http.Client{}
    	resp, err := client.Do(req)
    	defer resp.Body.Close()
    }
    
  4. demo ディレクトリに切り替えます。instgo ツールを使用してプログラムをビルドし、実行します。

    $ ./instgo set --rule=../config.json
    $ INSTGO_CACHE_DIR=./ ./instgo go build net_http.go
    # Linux システムで実行する必要がある場合
    CGO_ENABLED=0 GOOS=linux GOARCH=amd64 INSTGO_CACHE_DIR=./ ./instgo go build net_http.go
    $ ./net_http

    次の出力は、拡張機能が正常に挿入されたことを示しています。

    request header is  {"Otelbuild":["true"]}
    response header is  {"Content-Type":["application/x-gzip"],"Date":["Mon, 04 Nov 2024 09:10:48 GMT"],"Server":["bfe"]}

    完全なコード例については、「nethttp」をご参照ください。

    説明

    リクエストヘッダーとレスポンスヘッダーのキャプチャに加えて、SQL インジェクション検出、カスタムロギング、リクエストパラメーターとレスポンスパラメーターへのアクセスなど、他の目的にもカスタム拡張を使用できます。