Application Real-Time Monitoring (ARMS) agent untuk Go menyediakan ekstensi kustom yang memungkinkan Anda menyisipkan fungsionalitas khusus tanpa mengubah kode sumber aplikasi. Fitur ini membantu menangani masalah dengan menangkap data dari parameter permintaan dan badan permintaan. Topik ini menggunakan Net/HTTP sebagai contoh untuk menunjukkan cara menangkap header permintaan dan respons menggunakan ekstensi tersebut.
Prasyarat
-
Pastikan aplikasi Anda berjalan pada Go 1.18 atau versi yang lebih baru.
-
Aplikasi Go Anda telah diintegrasikan dengan Application Real-Time Monitoring (ARMS).
PentingPastikan perintah build telah dimodifikasi menjadi
./instgo go build xxxsesuai yang ditentukan dalam dokumentasi integrasi.
Batasan
-
Anda tidak dapat menggunakan ekstensi kustom untuk melakukan instrumentasi terhadap user-defined function dalam
package main. -
Anda tidak dapat menggunakan ekstensi kustom untuk melakukan instrumentasi terhadap fungsi yang ReceiverType-nya adalah
any.
Spesifikasi kode
-
Jangan gunakan
package maindalam kode hook Anda. -
Jika Anda menggunakan kode dari versi 2.0.0 atau yang lebih baru, tambahkan
"_ unsafe"ke dalam pernyataan import, seperti berikut:import ( "encoding/json" "fmt" "github.com/alibaba/loongsuite-go-agent/pkg/api" "net/http" _ "unsafe" ) -
Parameter pertama fungsi OnEnter selalu berupa
call api.CallContext, parameter kedua adalah ReceiverType (jika ada), dan parameter berikutnya adalah parameter permintaan dari fungsi yang disisipi.CatatanJika
ReceiverTypemengandung*, Anda harus menambahkan awalan\\dalam file JSON untuk melakukan escape karakter tersebut. -
Parameter pertama fungsi
OnExitbersifat tetap sebagaicall api.CallContext, sedangkan parameter berikutnya adalah nilai kembali dari fungsi yang disisipi, yang ditentukan secara berurutan.
Sebagai contoh, fungsi net/http::(*Transport).RoundTrip adalah sebagai berikut:
func (t *Transport) RoundTrip(req *Request) (*Response, error) {
return t.roundTrip(req)
}
Karena ReceiverType dari RoundTrip adalah *Transport, maka parameter kedua fungsi OnEnter adalah *Transport dan parameter ketiga adalah req *Request. Parameter kedua dan ketiga fungsi OnExit adalah nilai kembali dari RoundTrip: *Response, error.
Jika ReceiverType merupakan tipe yang tidak diekspor (unexported), Anda dapat menggunakan _ interface{} sebagai pengganti. Demikian pula, jika terdapat parameter yang ingin Anda abaikan, Anda dapat menggunakan _ interface{} sebagai pengganti.
Prosedur
-
Di direktori di luar proyek Anda saat ini, buat folder bernama
rules, inisialisasi dengan menjalankan perintahgo mod init rules, lalu buat file bernamarules.godi dalam folder tersebut dengan kode berikut.Kode ini mendefinisikan ekstensi kustom.
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)) } -
Modifikasi file
config.jsondan tambahkan konten berikut untuk menyisipkan kode hook ke dalamnet/http::(*Transport).RoundTrip.[ { "ImportPath":"net/http", "Function":"RoundTrip", "OnEnter":"httpClientEnterHook1", "ReceiverType": "\\*Transport", "OnExit": "httpClientExitHook1", "Path": "/extension/rules" // Ganti dengan jalur mutlak ke folder rules. } ] -
Buat demo pengujian.
Di direktori selain folder
rules, buat folder untuk aplikasi demo dan inisialisasi dengan perintahgo mod init demo. Kemudian, buat filenet_http.goyang berisi kode berikut di dalam folderdemo.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() } -
Beralih ke direktori
demo. Gunakan tool instgo untuk mem-build dan menjalankan program.$ ./instgo set --rule=../config.json $ INSTGO_CACHE_DIR=./ ./instgo go build net_http.go # Jika Anda perlu menjalankan pada sistem Linux CGO_ENABLED=0 GOOS=linux GOARCH=amd64 INSTGO_CACHE_DIR=./ ./instgo go build net_http.go $ ./net_httpOutput berikut mengonfirmasi bahwa ekstensi berhasil disisipkan.
request header is {"Otelbuild":["true"]} response header is {"Content-Type":["application/x-gzip"],"Date":["Mon, 04 Nov 2024 09:10:48 GMT"],"Server":["bfe"]}Untuk contoh kode lengkap, lihat nethttp.
CatatanSelain menangkap header permintaan dan respons, Anda dapat menggunakan ekstensi kustom untuk tujuan lain, seperti deteksi Injeksi SQL, logging kustom, serta mengakses parameter permintaan dan respons.