使用Golang探针的自定义扩展能力

更新时间:2025-02-28 02:26:43

Golang探针提供自定义扩展能力,您可以在不修改原有代码的基础上注入自定义功能,从而实现通过请求参数、Body来定位问题。本文以Net/HTTP为例介绍如何使用Golang探针的自定义扩展能力获取请求头和响应头。

前提条件

  • 确认当前应用的Golang版本在1.18及以上。

  • Golang应用接入到ARMS

    重要

    请确认编译语句已参考接入文档修改为./instgo go build xxx

编写规范

  • OnEnter函数第一个参数固定为call api.CallContext,第二个参数为ReceiverType(如果有),后续参数为插入函数的入参。

  • OnExit函数第一个参数固定为call api.CallContext,后续参数依次填写插入函数的返回值。

例如,net/http::(*Transport).RoundTrip函数如下所示:

func (t *Transport) RoundTrip(req *Request) (*Response, error) {
	return t.roundTrip(req)
}

RoundTripReceiverType*Transport,所以OnEnter函数的第二参数为*Transport,第三个参数为req *Request;OnExit函数的第二个、第三个参数为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"
    )
    
    func httpClientEnterHook(call api.CallContext, t *http.Transport, req *http.Request) {
    	header, _ := json.Marshal(req.Header)
    	fmt.Println("request header is ", string(header))
    }
    
    func httpClientExitHook(call api.CallContext, res *http.Response, err error) {
    	header, _ := json.Marshal(res.Header)
    	fmt.Println("response header is ", string(header))
    }
    
  2. 修改config.json配置文件,添加以下内容将hook代码注入到net/http::(*Transport).RoundTrip

    [
      {
        "ImportPath":"net/http",
        "Function":"RoundTrip",
        "OnEnter":"httpClientEnterHook",
        "ReceiverType": "*Transport",
        "OnExit": "httpClientExitHook",
        "Path": "/extension/rules" //替换为rules文件夹的绝对路径
      }
    ]
  3. 编写测试Demo。

    在不同于rules文件夹的目录下创建一个demo应用的文件夹,并使用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

    说明

    除了上述介绍的通过扩展方式打印请求和返回的Header外,自定义扩展能力还可以用于SQL注入检测、日志打印、出参和入参打印等。

  • 本页导读 (1)
  • 前提条件
  • 编写规范
  • 操作步骤
AI助理

点击开启售前

在线咨询服务

你好,我是AI助理

可以解答问题、推荐解决方案等