Agen Golang menyediakan fitur ekstensi kustom yang memungkinkan Anda menyisipkan fungsi kustom tanpa mengubah kode asli. Fitur ini membantu mengidentifikasi masalah dengan memeriksa parameter dan isi permintaan (request). Topik ini menggunakan Net/HTTP sebagai contoh untuk menunjukkan cara menggunakan fitur ekstensi kustom agen Golang guna mengambil header permintaan dan respons.
Prasyarat
Pastikan aplikasi Anda menggunakan Golang 1.18 atau versi yang lebih baru.
Anda telah menghubungkan aplikasi Golang Anda ke ARMS.
PentingPastikan pernyataan kompilasi telah diubah menjadi
./instgo go build xxxsebagaimana dijelaskan dalam dokumen integrasi.
Batasan
Fitur ekstensi kustom tidak mendukung instrumentasi untuk fungsi pengguna dalam package main.
Fitur ekstensi kustom tidak mendukung instrumentasi untuk fungsi yang ReceiverType-nya adalah `any`.
Spesifikasi
Jangan gunakan package main dalam kode hook.
Jika Anda menggunakan kode versi 2.0.0 atau yang lebih baru, tambahkan
"_ unsafe"ke pernyataan import seperti berikut:import ( "encoding/json" "fmt" "github.com/alibaba/loongsuite-go-agent/pkg/api" "net/http" _ "unsafe" )Parameter pertama fungsi OnEnter harus berupa
call api.CallContext. Parameter kedua, jika ada, adalah ReceiverType. Parameter selanjutnya merupakan parameter input dari fungsi yang diinstrumentasi.CatatanJika ReceiverType mengandung
*, Anda harus menambahkan awalan\\dalam file JSON untuk melakukan escape karakter tersebut.Parameter pertama fungsi OnExit harus berupa
call api.CallContext. Parameter selanjutnya merupakan nilai kembali dari fungsi yang diinstrumentasi.
Sebagai contoh, fungsi net/http::(*Transport).RoundTrip adalah sebagai berikut:
func (t *Transport) RoundTrip(req *Request) (*Response, error) {
return t.roundTrip(req)
}Receiver type dari RoundTrip adalah *Transport. Oleh karena itu, parameter kedua fungsi OnEnter adalah *Transport dan parameter ketiga adalah req *Request. Parameter kedua dan ketiga fungsi OnExit adalah nilai kembali dari RoundTrip, yaitu *Response, error.
Jika ReceiverType merupakan kelas yang tidak diekspos (dimulai dengan huruf kecil), gunakan _ interface{} sebagai tipenya. Anda juga dapat menggunakan _ interface{} sebagai placeholder untuk parameter apa pun yang ingin Anda abaikan.
Prosedur
Buat folder `rules` di luar direktori proyek Anda saat ini. Inisialisasi folder tersebut dengan menjalankan perintah
go mod init rules. Kemudian, buat file `rules.go` di folder `rules` yang berisi kode berikut.Kode ini mendefinisikan fungsi ekstensi kustom yang akan disisipkan.
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)) }Ubah file konfigurasi config.json. Tambahkan konten berikut untuk menyisipkan kode hook ke
net/http::(*Transport).RoundTrip.[ { "ImportPath":"net/http", "Function":"RoundTrip", "OnEnter":"httpClientEnterHook1", "ReceiverType": "\\*Transport", "OnExit": "httpClientExitHook1", "Path": "/extension/rules" // Ganti dengan jalur mutlak folder rules } ]Buat aplikasi contoh.
Di direktori di luar folder `rules`, buat folder baru untuk aplikasi sampel. Inisialisasi folder ini dengan menjalankan perintah
go mod init demo. Kemudian, buat file `net_http.go` di folder `demo` yang berisi kode berikut.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() }Berpindah ke direktori demo. Gunakan tool instgo untuk mengompilasi dan menjalankan program.
$ ./instgo set --rule=../config.json $ INSTGO_CACHE_DIR=./ ./instgo go build net_http.go # Untuk menjalankan di Linux CGO_ENABLED=0 GOOS=linux GOARCH=amd64 INSTGO_CACHE_DIR=./ ./instgo go build net_http.go $ ./net_httpJika output berikut ditampilkan, hal ini menunjukkan bahwa penyisipan berhasil dan ekstensi aktif.

Untuk contoh kode lengkap, lihat nethttp.
CatatanSelain mengambil header permintaan dan respons, Anda juga dapat menggunakan fitur ekstensi kustom untuk tujuan lain, seperti deteksi Injeksi SQL, logging kustom, serta pengambilan parameter permintaan dan respons.