mirror of
https://gitee.com/johng/gf.git
synced 2024-12-03 12:47:50 +08:00
177 lines
4.4 KiB
Go
177 lines
4.4 KiB
Go
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
|
//
|
|
// This Source Code Form is subject to the terms of the MIT License.
|
|
// If a copy of the MIT was not distributed with this file,
|
|
// You can obtain one at https://github.com/gogf/gf.
|
|
|
|
package gclient
|
|
|
|
import (
|
|
"context"
|
|
"crypto/tls"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"net/http/httptrace"
|
|
"net/textproto"
|
|
"strings"
|
|
"sync"
|
|
|
|
"github.com/gogf/gf/v2/internal/utils"
|
|
"github.com/gogf/gf/v2/net/gtrace"
|
|
"github.com/gogf/gf/v2/text/gstr"
|
|
"github.com/gogf/gf/v2/util/gconv"
|
|
"go.opentelemetry.io/otel/attribute"
|
|
"go.opentelemetry.io/otel/codes"
|
|
"go.opentelemetry.io/otel/trace"
|
|
)
|
|
|
|
type clientTracer struct {
|
|
context.Context
|
|
span trace.Span
|
|
request *http.Request
|
|
requestBody []byte
|
|
headers map[string]interface{}
|
|
mtx sync.Mutex
|
|
}
|
|
|
|
func newClientTrace(ctx context.Context, span trace.Span, request *http.Request) *httptrace.ClientTrace {
|
|
ct := &clientTracer{
|
|
Context: ctx,
|
|
span: span,
|
|
request: request,
|
|
headers: make(map[string]interface{}),
|
|
}
|
|
|
|
reqBodyContent, _ := ioutil.ReadAll(ct.request.Body)
|
|
ct.requestBody = reqBodyContent
|
|
ct.request.Body = utils.NewReadCloser(reqBodyContent, false)
|
|
|
|
return &httptrace.ClientTrace{
|
|
GetConn: ct.getConn,
|
|
GotConn: ct.gotConn,
|
|
PutIdleConn: ct.putIdleConn,
|
|
GotFirstResponseByte: ct.gotFirstResponseByte,
|
|
Got100Continue: ct.got100Continue,
|
|
Got1xxResponse: ct.got1xxResponse,
|
|
DNSStart: ct.dnsStart,
|
|
DNSDone: ct.dnsDone,
|
|
ConnectStart: ct.connectStart,
|
|
ConnectDone: ct.connectDone,
|
|
TLSHandshakeStart: ct.tlsHandshakeStart,
|
|
TLSHandshakeDone: ct.tlsHandshakeDone,
|
|
WroteHeaderField: ct.wroteHeaderField,
|
|
WroteHeaders: ct.wroteHeaders,
|
|
Wait100Continue: ct.wait100Continue,
|
|
WroteRequest: ct.wroteRequest,
|
|
}
|
|
}
|
|
|
|
func (ct *clientTracer) getConn(host string) {
|
|
|
|
}
|
|
|
|
func (ct *clientTracer) gotConn(info httptrace.GotConnInfo) {
|
|
ct.span.SetAttributes(
|
|
attribute.String(tracingAttrHttpAddressRemote, info.Conn.RemoteAddr().String()),
|
|
attribute.String(tracingAttrHttpAddressLocal, info.Conn.LocalAddr().String()),
|
|
)
|
|
}
|
|
|
|
func (ct *clientTracer) putIdleConn(err error) {
|
|
if err != nil {
|
|
ct.span.SetStatus(codes.Error, fmt.Sprintf(`%+v`, err))
|
|
}
|
|
}
|
|
|
|
func (ct *clientTracer) dnsStart(info httptrace.DNSStartInfo) {
|
|
ct.span.SetAttributes(
|
|
attribute.String(tracingAttrHttpDnsStart, info.Host),
|
|
)
|
|
}
|
|
|
|
func (ct *clientTracer) dnsDone(info httptrace.DNSDoneInfo) {
|
|
var buffer strings.Builder
|
|
for _, v := range info.Addrs {
|
|
if buffer.Len() != 0 {
|
|
buffer.WriteString(",")
|
|
}
|
|
buffer.WriteString(v.String())
|
|
}
|
|
if info.Err != nil {
|
|
ct.span.SetStatus(codes.Error, fmt.Sprintf(`%+v`, info.Err))
|
|
}
|
|
ct.span.SetAttributes(
|
|
attribute.String(tracingAttrHttpDnsDone, buffer.String()),
|
|
)
|
|
}
|
|
|
|
func (ct *clientTracer) connectStart(network, addr string) {
|
|
ct.span.SetAttributes(
|
|
attribute.String(tracingAttrHttpConnectStart, network+"@"+addr),
|
|
)
|
|
}
|
|
|
|
func (ct *clientTracer) connectDone(network, addr string, err error) {
|
|
if err != nil {
|
|
ct.span.SetStatus(codes.Error, fmt.Sprintf(`%+v`, err))
|
|
}
|
|
ct.span.SetAttributes(
|
|
attribute.String(tracingAttrHttpConnectDone, network+"@"+addr),
|
|
)
|
|
}
|
|
|
|
func (ct *clientTracer) tlsHandshakeStart() {
|
|
|
|
}
|
|
|
|
func (ct *clientTracer) tlsHandshakeDone(_ tls.ConnectionState, err error) {
|
|
if err != nil {
|
|
ct.span.SetStatus(codes.Error, fmt.Sprintf(`%+v`, err))
|
|
}
|
|
}
|
|
|
|
func (ct *clientTracer) wroteHeaderField(k string, v []string) {
|
|
if len(v) > 1 {
|
|
ct.headers[k] = v
|
|
} else {
|
|
ct.headers[k] = v[0]
|
|
}
|
|
}
|
|
|
|
func (ct *clientTracer) wroteHeaders() {
|
|
|
|
}
|
|
|
|
func (ct *clientTracer) wroteRequest(info httptrace.WroteRequestInfo) {
|
|
if info.Err != nil {
|
|
ct.span.SetStatus(codes.Error, fmt.Sprintf(`%+v`, info.Err))
|
|
}
|
|
|
|
ct.span.AddEvent(tracingEventHttpRequest, trace.WithAttributes(
|
|
attribute.String(tracingEventHttpRequestHeaders, gconv.String(ct.headers)),
|
|
attribute.String(tracingEventHttpRequestBaggage, gtrace.GetBaggageMap(ct.Context).String()),
|
|
attribute.String(tracingEventHttpRequestBody, gstr.StrLimit(
|
|
string(ct.requestBody),
|
|
gtrace.MaxContentLogSize(),
|
|
"...",
|
|
)),
|
|
))
|
|
}
|
|
|
|
func (ct *clientTracer) got100Continue() {
|
|
|
|
}
|
|
|
|
func (ct *clientTracer) wait100Continue() {
|
|
|
|
}
|
|
|
|
func (ct *clientTracer) gotFirstResponseByte() {
|
|
|
|
}
|
|
|
|
func (ct *clientTracer) got1xxResponse(code int, header textproto.MIMEHeader) error {
|
|
return nil
|
|
}
|