diff --git a/go.mod b/go.mod index a337850..ce9c9a4 100644 --- a/go.mod +++ b/go.mod @@ -7,4 +7,5 @@ require ( github.com/json-iterator/go v1.1.12 github.com/modern-go/reflect2 v1.0.2 golang.org/x/net v0.11.0 + github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b ) diff --git a/tea/tea.go b/tea/tea.go index c984caf..0881ef9 100644 --- a/tea/tea.go +++ b/tea/tea.go @@ -26,6 +26,8 @@ import ( "github.com/alibabacloud-go/debug/debug" "github.com/alibabacloud-go/tea/utils" + opentracing "github.com/opentracing/opentracing-go" + "github.com/opentracing/opentracing-go/ext" "golang.org/x/net/proxy" ) @@ -97,6 +99,8 @@ type RuntimeObject struct { Listener utils.ProgressListener `json:"listener" xml:"listener"` Tracker *utils.ReaderTracker `json:"tracker" xml:"tracker"` Logger *utils.Logger `json:"logger" xml:"logger"` + Span *opentracing.Span `json:"span" xml:"span"` + IsCloseTrace *bool `json:"isCloseTrace" xml:"isCloseTrace"` } type teaClient struct { @@ -133,6 +137,7 @@ func NewRuntimeObject(runtime map[string]interface{}) *RuntimeObject { Key: TransInterfaceToString(runtime["key"]), Cert: TransInterfaceToString(runtime["cert"]), CA: TransInterfaceToString(runtime["ca"]), + IsCloseTrace: TransInterfaceToBool(runtime["isCloseTrace"]), } if runtime["listener"] != nil { runtimeObject.Listener = runtime["listener"].(utils.ProgressListener) @@ -143,6 +148,9 @@ func NewRuntimeObject(runtime map[string]interface{}) *RuntimeObject { if runtime["logger"] != nil { runtimeObject.Logger = runtime["logger"].(*utils.Logger) } + if runtime["span"] != nil { + runtimeObject.Span = runtime["span"].(*opentracing.Span) + } return runtimeObject } @@ -378,6 +386,31 @@ func DoRequest(request *Request, requestRuntime map[string]interface{}) (respons event := utils.NewProgressEvent(utils.TransferStartedEvent, 0, int64(contentlength), 0) utils.PublishProgress(runtimeObject.Listener, event) + // Set tracer + var span opentracing.Span + if ok := opentracing.IsGlobalTracerRegistered(); ok && BoolValue(runtimeObject.IsCloseTrace) != true { + tracer := opentracing.GlobalTracer() + var rootCtx opentracing.SpanContext + var rootSpan opentracing.Span + + if runtimeObject.Span != nil { + rootSpan = *runtimeObject.Span + rootCtx = rootSpan.Context() + } + + span = tracer.StartSpan( + httpRequest.URL.RequestURI(), + opentracing.ChildOf(rootCtx), + opentracing.Tag{Key: string(ext.Component), Value: "aliyunApi"}, + opentracing.Tag{Key: "request", Value: requestURL}) + + defer span.Finish() + tracer.Inject( + span.Context(), + opentracing.HTTPHeaders, + opentracing.HTTPHeadersCarrier(httpRequest.Header)) + } + putMsgToMap(fieldMap, httpRequest) startTime := time.Now() fieldMap["{start_time}"] = startTime.Format("2006-01-02 15:04:05") @@ -984,7 +1017,7 @@ func validatePtr(field reflect.StructField, elementValue reflect.Value, contains } } } - } else { + } else if elementValue.Elem().Type().Kind() == reflect.Struct { err := validate(elementValue) if err != nil { return err diff --git a/tea/tea_test.go b/tea/tea_test.go index 297456f..a43426c 100644 --- a/tea/tea_test.go +++ b/tea/tea_test.go @@ -16,6 +16,8 @@ import ( "time" "github.com/alibabacloud-go/tea/utils" + opentracing "github.com/opentracing/opentracing-go" + "github.com/opentracing/opentracing-go/ext" ) type test struct { @@ -47,18 +49,19 @@ var runtimeObj = map[string]interface{}{ } type validateTest struct { - Num1 *int `json:"num1,omitempty" require:"true" minimum:"2"` - Num2 *int `json:"num2,omitempty" maximum:"6"` - Name1 *string `json:"name1,omitempty" maxLength:"4"` - Name2 *string `json:"name2,omitempty" minLength:"2"` - Str *string `json:"str,omitempty" pattern:"[a-d]*" maxLength:"4"` - MaxLength *errMaxLength `json:"MaxLength,omitempty"` - MinLength *errMinLength `json:"MinLength,omitempty"` - Maximum *errMaximum `json:"Maximum,omitempty"` - Minimum *errMinimum `json:"Minimum,omitempty"` - MaxItems *errMaxItems `json:"MaxItems,omitempty"` - MinItems *errMinItems `json:"MinItems,omitempty"` - List []*string `json:"list,omitempty" pattern:"[a-d]*" minItems:"2" maxItems:"3" maxLength:"4"` + Num1 *int `json:"num1,omitempty" require:"true" minimum:"2"` + Num2 *int `json:"num2,omitempty" maximum:"6"` + Name1 *string `json:"name1,omitempty" maxLength:"4"` + Name2 *string `json:"name2,omitempty" minLength:"2"` + Str *string `json:"str,omitempty" pattern:"[a-d]*" maxLength:"4"` + MaxLength *errMaxLength `json:"MaxLength,omitempty"` + MinLength *errMinLength `json:"MinLength,omitempty"` + Maximum *errMaximum `json:"Maximum,omitempty"` + Minimum *errMinimum `json:"Minimum,omitempty"` + MaxItems *errMaxItems `json:"MaxItems,omitempty"` + MinItems *errMinItems `json:"MinItems,omitempty"` + List []*string `json:"list,omitempty" pattern:"[a-d]*" minItems:"2" maxItems:"3" maxLength:"4"` + PtrNotStruct *opentracing.Span `json:"span" xml:"span"` } type errMaxLength struct { @@ -748,6 +751,17 @@ func Test_Validate(t *testing.T) { err := Validate(config) utils.AssertNil(t, err) + tracer := opentracing.GlobalTracer() + span := tracer.StartSpan( + "aliyuncs.com/test", + opentracing.Tag{Key: string(ext.Component), Value: "aliyunApi"}, + opentracing.Tag{Key: "request", Value: "test"}) + config = &validateTest{ + PtrNotStruct: &span, + } + err = Validate(config) + utils.AssertNil(t, err) + err = Validate(new(validateTest)) utils.AssertEqual(t, err.Error(), "num1 should be setted")