The Application Real-Time Monitoring (ARMS) agent for Go provides custom extensions. You can add custom features without changing the code, facilitating error location based on request parameters and the request body. This topic takes Net/HTTP as an example to describe how to use custom extensions of the ARMS agent for Go to capture request and response headers.
Apart from printing request and response headers, this capability can also be used to detect SQL injection, output logs, and print response and request parameters.
Prerequisites
The application is running on Go V1.18 or later.
Your Go application is monitored by ARMS.
ImportantEnsure that the compilation is changed to
./instgo go build xxxas required by the reference document.
Limits
The following functions cannot be instrumented:
The functions in
package mainThe functions whose
ReceiverTypeisany
Code specifications
Do not use
package mainin Hook code.If you use code V2.0.0 or later, add
"_ unsafe"to the import statement:import ( "encoding/json" "fmt" "github.com/alibaba/opentelemetry-go-auto-instrumentation/pkg/api" "net/http" "_ unsafe" )OnEnterfunction: takescall api.CallContextas the first parameter andReceiverTypeas the second if any, followed by the input parameters of instrumentation functions.NoteIf
ReceiverTypecontains an asterisk, add the\\prefix in the JSON file to escape it.OnExitfunction: takescall api.CallContextas the first parameter, followed by the values returned from instrumentation functions.
Take the net/http::(*Transport).RoundTrip function for example:
func (t *Transport) RoundTrip(req *Request) (*Response, error) {
return t.roundTrip(req)
}When the ReceiverType of RoundTrip is *Transport:
OnEnterparameters:call api.CallContext,*Transport,req *RequestOnExitparameters:call api.CallContext,*Response, error(the values returned fromRoundTrip)
If the ReceiverType is a non-exported type or you want to leave certain parameters empty, you can use _ interface{} instead.
Procedure
Outside the directory of the current project, create a folder named
rulesand run thego mod init rulescommand to initialize it. In therulesfolder, create a file namedrules.gowith the following code, which provides custom extensions: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 httpClientEnterHook(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 httpClientExitHook(call api.CallContext, res *http.Response, err error) { header, _ := json.Marshal(res.Header) fmt.Println("response header is ", string(header)) }In the
config.jsonconfiguration file, add the following code tonet/http::(*Transport).RoundTrip:[ { "ImportPath":"net/http", "Function":"RoundTrip", "OnEnter":"httpClientEnterHook1", "ReceiverType": "\\*Transport", "OnExit": "httpClientExitHook1", "Path": "/extension/rules" //Specify the absolute path of the rules folder. } ]Develop a test demo.
In a separate directory from the
rulesfolder, create a demo application folder and run thego mod init democommand to initialize it. In thedemofolder, create a file namednet_http.gowith the following code: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() }Go to the
demodirectory and use instgo to compile and run the program.$ ./instgo set --rule=../config.json $ INSTGO_CACHE_DIR=./ ./instgo go build net_http.go To run the application on a Linux system: CGO_ENABLED=0 GOOS=linux GOARCH=amd64 INSTGO_CACHE_DIR=./ ./instgo go build net_http.go $ Run ./net_httpIf the following output appears, the capability has been added and the plug-in has taken effect:

For information about the complete sample code, see nethttp.