Generates interface decorators with DataDog Distributes Tracing support.
go get github.com/r3code/dd-trace-wrap-gen dd-trace-wrap-gen -i <an interface to decortate> -o <output_file> <file_source_folder_path> Params:
- -i - specify interface name
- -o - output filename
- -s - target struct name, default: WithTracing
Interface being decorated
type TestInterface interface { F(ctx context.Context, a1 string, a2 ...string) (result1, result2 string, err error) NoErrorWithContext(context.Context, string) string NoError(string) string NoParamsOrResults() Channels(chA chan bool, chB chan<- bool, chanC <-chan bool) }To create a new wrapper use:
dd-trace-wrap-gen -i TestInterface -o ./tests/interface_with_datadog_trace.go ./tests Will generate:
package tests // Code generated by github.com/r3code/dd-trace-wrap-gen tool. DO NOT EDIT! // import ( "context" "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" ) // TestInterfaceWithTracing implements TestInterface interface instrumented with datadog spans type TestInterfaceWithTracing struct { TestInterface _spanName string _spanDecorator func(span tracer.Span, params, results map[string]interface{}) _errorMarkDecider func(err error) bool } // NewTestInterfaceWithTracing returns TestInterfaceWithTracing for the base service with a specified // Datadog’s span name spanName (equals OpenTracing “component” tag), and allows to add extra data to the span by spanDecorator (a func to add some extra tags for a span). // Pass nil if you don't need decorations. // You can skip marking a span with an error mark by returning false in errorMarkDecider func. Optional, by default the decider always returns true. // // Note: when using Datadog, the OpenTracing operation name is a resource and the OpenTracing “component” tag is Datadog’s span name. // SpanName in DataDog becomes an "operation name" and "resource name" is taken from $method.Name // Example. Create a span for a http request for url /user/profile: // spanName = "http.request" // resource = "/user/profile" func NewTestInterfaceWithTracing(base TestInterface, spanName string, spanDecorator func(span tracer.Span, params, results map[string]interface{}), errorMarkDecider ...func(err error) bool) TestInterfaceWithTracing { d := TestInterfaceWithTracing{ TestInterface: base, _spanName: spanName, _errorMarkDecider: func(err error) bool { return true }, // by default always allow mark a span having an error } if spanDecorator != nil { d._spanDecorator = spanDecorator } if len(errorMarkDecider) > 0 && errorMarkDecider[0] != nil { d._errorMarkDecider = errorMarkDecider[0] } return d } // F implements TestInterface func (_d TestInterfaceWithTracing) F(ctx context.Context, a1 string, a2 ...string) (result1 string, result2 string, err error) { _span, ctx := tracer.StartSpanFromContext(ctx, _d._spanName, tracer.ResourceName("F")) defer func() { if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, "a1": a1, "a2": a2}, map[string]interface{}{ "result1": result1, "result2": result2, "err": err}) } var opts []tracer.FinishOption if err != nil && _d._errorMarkDecider(err) { opts = append(opts, tracer.WithError(err)) } _span.Finish(opts...) }() return _d.TestInterface.F(ctx, a1, a2...) } // NoErrorWithContext implements TestInterface func (_d TestInterfaceWithTracing) NoErrorWithContext(ctx context.Context, s1 string) (s2 string) { _span, ctx := tracer.StartSpanFromContext(ctx, _d._spanName, tracer.ResourceName("NoErrorWithContext")) defer func() { if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, "s1": s1}, map[string]interface{}{ "s2": s2}) } _span.Finish() }() return _d.TestInterface.NoErrorWithContext(ctx, s1) }