All Products
Search
Document Center

Application Real-Time Monitoring Service:Use the custom extensions of the ARMS agent for Go

Last Updated:Nov 11, 2025

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.

Note

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.

    Important

    Ensure that the compilation is changed to ./instgo go build xxx as required by the reference document.

Limits

The following functions cannot be instrumented:

  • The functions in package main

  • The functions whose ReceiverType is any

Code specifications

  • Do not use package main in 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"
    )
  • OnEnter function: takes call api.CallContext as the first parameter and ReceiverType as the second if any, followed by the input parameters of instrumentation functions.

    Note

    If ReceiverType contains an asterisk, add the \\ prefix in the JSON file to escape it.

  • OnExit function: takes call api.CallContext as 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:

  • OnEnter parameters: call api.CallContext, *Transport, req *Request

  • OnExit parameters: call api.CallContext, *Response, error (the values returned from RoundTrip)

If the ReceiverType is a non-exported type or you want to leave certain parameters empty, you can use _ interface{} instead.

Procedure

  1. Outside the directory of the current project, create a folder named rules and run the go mod init rules command to initialize it. In the rules folder, create a file named rules.go with 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))
    }
  2. In the config.json configuration file, add the following code to net/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.
      }
    ]
  3. Develop a test demo.

    In a separate directory from the rules folder, create a demo application folder and run the go mod init demo command to initialize it. In the demo folder, create a file named net_http.go with 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()
    
    }
    
  4. Go to the demo directory 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_http

    If the following output appears, the capability has been added and the plug-in has taken effect:

    image.png

    For information about the complete sample code, see nethttp.