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

Application Real-Time Monitoring Service:Golang エージェントのカスタム拡張機能を使用する

最終更新日:Nov 30, 2025

Golang エージェントは、元のコードを変更することなくカスタム関数を注入できるカスタム拡張機能を提供します。これにより、リクエストパラメーターとリクエストボディを検査して問題を特定できます。このトピックでは、Net/HTTP を例として、Golang エージェントのカスタム拡張機能を使用してリクエストヘッダーとレスポンスヘッダーを取得する方法を説明します。

前提条件

制限事項

  • カスタム拡張機能は、`package main` 内のユーザー関数のインストルメンテーションをサポートしていません。

  • カスタム拡張機能は、ReceiverType が `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 のレシーバータイプは *Transport です。したがって、OnEnter 関数の 2 番目のパラメーターは *Transport で、3 番目のパラメーターは req *Request です。OnExit 関数の 2 番目と 3 番目のパラメーターは RoundTrip の戻り値であり、*Response, error です。

ReceiverType が小文字で始まる非公開クラスである場合は、その型として _ interface{} を使用します。また、省略したいパラメーターのプレースホルダーとして _ interface{} を使用することもできます。

手順

  1. 現在のプロジェクトディレクトリの外に `rules` フォルダを作成します。go mod init rules コマンドを実行してフォルダを初期化します。次に、`rules` フォルダに `rules.go` ファイルを作成し、次のコードを含めます。

    このコードは、注入するカスタム拡張機能を定義します。

    package rules
    
    import (
    	"encoding/json"
    	"fmt"
    	"github.com/alibaba/opentelemetry-go-auto-instrumentation/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

    次の出力が表示された場合、注入が成功し、拡張機能がアクティブであることを示します。

    image.png

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

    説明

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