繁体   English   中英

如何在 Go 中使用 httptrace 跟踪 http.Client

[英]How to trace http.Client with httptrace in Go

根据此文档,我们可以通过这种方式使用httptrace跟踪http.Client

    t := &transport{}

    req, _ := http.NewRequest("GET", "https://google.com", nil)
    trace := &httptrace.ClientTrace{
        GotConn: t.GotConn,
    }
    req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))

    client := &http.Client{Transport: t}

对于谷歌 API 客户端,这里是一个包装器代码

func NewWithClient(jsonKey []byte, cli *http.Client) (*Client, error) {
    if cli == nil {
        return nil, fmt.Errorf("client is nil")
    }

    ctx := context.WithValue(context.Background(), oauth2.HTTPClient, cli)

    conf, err := google.JWTConfigFromJSON(jsonKey, androidpublisher.AndroidpublisherScope)
    if err != nil {
        return nil, err
    }

    service, err := androidpublisher.NewService(ctx, option.WithHTTPClient(conf.Client(ctx)))
    if err != nil {
        return nil, err
    }

    return &Client{service}, err
}

我们想申请httptracehttp.Client的说法NewWithClient做HTTP跟踪。

我们尝试过的

type TraceTransport struct {
}

var traceTransport = &TraceTransport{}

var trace = &httptrace.ClientTrace{
    GotConn: traceTransport.GotConn,
}

func (t *TraceTransport) RoundTrip(req *http.Request) (*http.Response, error) {
    return http.DefaultTransport.RoundTrip(req)
}

func (t *TraceTransport) GotConn(info httptrace.GotConnInfo) {
    fmt.Printf("Connection reused for %v \n", info.Reused)
}

type ClientWrapper struct {
    defaultClient *http.Client
}

var clientWrapperTrace = &httptrace.ClientTrace{GotConn: traceTransport.GotConn}

func (c *ClientWrapper) Do(req *http.Request) (*http.Response, error) {
    req = req.WithContext(httptrace.WithClientTrace(req.Context(), clientWrapperTrace))
    return c.defaultClient.Do(req)
}

func NewClientTrace(jsonKey []byte) (*Client, error) {
    cli := &http.Client{
        Transport: traceTransport,
        Timeout:   time.Duration(10) * time.Second,
    }
    cliWrapper := &ClientWrapper{defaultClient: cli}
    ctx := context.WithValue(context.Background(), oauth2.HTTPClient, cliWrapper)

    conf, err := google.JWTConfigFromJSON(jsonKey, androidpublisher.AndroidpublisherScope)
    if err != nil {
        return nil, err
    }

    service, err := androidpublisher.NewService(ctx, option.WithHTTPClient(conf.Client(ctx)))
    if err != nil {
        return nil, err
    }

    return &Client{service}, err
}

type Client struct {
    service *androidpublisher.Service
}

func (c *Client) VerifyProduct(
    ctx context.Context,
    packageName string,
    productID string,
    token string,
) (*androidpublisher.ProductPurchase, error) {
    ps := androidpublisher.NewPurchasesProductsService(c.service)
    result, err := ps.Get(packageName, productID, token).Context(ctx).Do()

    return result, err
}

// test codes
  c, err := NewClientTrace([]byte(privateKey)) 
  if err != nil {
    return
  }

  packageName := "package.name"
  productID := "product_id"
  token := "xxxxx"
  r, err := c.VerifyProduct(context.Background(), packageName, productID, token)

但是,未能追查http.Client ,没有任何的输出GotConn 有人可以帮助我们找出上述代码的问题吗?

  1. httptrace无法追踪来自google/oauth2httptrace 您通过context.WithValue传递的ClientWrapper将在这里被忽略,而 oauth2 有它自己的 http.Client ,它只是使用来自 context.Value 的*http.ClientTransport方法。

  2. 来自 androidpublisher 的请求可以通过 httptrace 跟踪,如下所示:

ctx := httptrace.WithClientTrace(context.Background(), clientWrapperTrace)
r, err := c.VerifyProduct(ctx, packageName, productID, token)
  1. 如果您只想计算请求数,我认为覆盖http.Client.Transport是一种简单的方法。
type TraceTransport struct {
}

func (t *TraceTransport) RoundTrip(req *http.Request) (*http.Response, error) {
    fmt.Printf("RoundTrip hook %v\n", req.URL)
    return http.DefaultTransport.RoundTrip(req)
}

func NewClientTrace(jsonKey []byte) (*Client, error) {
    cli := &http.Client{Transport: &TraceTransport{}}
    ctx := context.WithValue(context.Background(), oauth2.HTTPClient, cli)

    // ...
    service, err := androidpublisher.NewService(ctx, option.WithHTTPClient(conf.Client(ctx)))
    // ....
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM