@@ -32,7 +32,6 @@ import (
3232 "github.com/labstack/echo/v4/middleware"
3333 "github.com/opentracing/opentracing-go"
3434 "github.com/opentracing/opentracing-go/ext"
35- "github.com/uber/jaeger-client-go"
3635 "github.com/uber/jaeger-client-go/config"
3736)
3837
@@ -64,20 +63,26 @@ var (
6463// Returns Closer do be added to caller function as `defer closer.Close()`
6564func New (e * echo.Echo , skipper middleware.Skipper ) io.Closer {
6665 // Add Opentracing instrumentation
67- cfg := config.Configuration {
66+ defcfg := config.Configuration {
67+ ServiceName : "echo-tracer" ,
6868 Sampler : & config.SamplerConfig {
6969 Type : "const" ,
7070 Param : 1 ,
7171 },
7272 Reporter : & config.ReporterConfig {
73- LogSpans : false ,
73+ LogSpans : true ,
7474 BufferFlushInterval : 1 * time .Second ,
7575 },
7676 }
77- tracer , closer , _ := cfg .New (
78- "echo-tracer" ,
79- config .Logger (jaeger .StdLogger ),
80- )
77+ cfg , err := defcfg .FromEnv ()
78+ if err != nil {
79+ panic ("Could not parse Jaeger env vars: " + err .Error ())
80+ }
81+ tracer , closer , err := cfg .NewTracer ()
82+ if err != nil {
83+ panic ("Could not initialize jaeger tracer: " + err .Error ())
84+ }
85+
8186 opentracing .SetGlobalTracer (tracer )
8287 e .Use (TraceWithConfig (TraceConfig {
8388 Tracer : tracer ,
@@ -87,7 +92,6 @@ func New(e *echo.Echo, skipper middleware.Skipper) io.Closer {
8792}
8893
8994// Trace returns a Trace middleware.
90- //
9195// Trace middleware traces http requests and reporting errors.
9296func Trace (tracer opentracing.Tracer ) echo.MiddlewareFunc {
9397 c := DefaultTraceConfig
@@ -149,45 +153,71 @@ func TraceWithConfig(config TraceConfig) echo.MiddlewareFunc {
149153
150154// TraceFunction wraps funtion with opentracing span adding tags for the function name and caller details
151155func TraceFunction (ctx echo.Context , fn interface {}, params ... interface {}) (result []reflect.Value ) {
152- f := reflect .ValueOf (fn )
153- if f .Type ().NumIn () != len (params ) {
154- panic ("incorrect number of parameters!" )
155- }
156- inputs := make ([]reflect.Value , len (params ))
157- for k , in := range params {
158- inputs [k ] = reflect .ValueOf (in )
159- }
160- pc , file , no , ok := runtime .Caller (1 )
161- details := runtime .FuncForPC (pc )
156+ // Get function name
162157 name := runtime .FuncForPC (reflect .ValueOf (fn ).Pointer ()).Name ()
158+ // Create child span
163159 parentSpan := opentracing .SpanFromContext (ctx .Request ().Context ())
164160 sp := opentracing .StartSpan (
165161 "Function - " + name ,
166162 opentracing .ChildOf (parentSpan .Context ()))
167- (opentracing.Tag {Key : "function" , Value : name }).Set (sp )
168- if ok {
169- callerDetails := fmt .Sprintf ("%s - %s#%d" , details .Name (), file , no )
170- (opentracing.Tag {Key : "caller" , Value : callerDetails }).Set (sp )
163+ defer sp .Finish ()
171164
165+ sp .SetTag ("function" , name )
166+
167+ // Get caller function name, file and line
168+ pc := make ([]uintptr , 15 )
169+ n := runtime .Callers (2 , pc )
170+ frames := runtime .CallersFrames (pc [:n ])
171+ frame , _ := frames .Next ()
172+ callerDetails := fmt .Sprintf ("%s - %s#%d" , frame .Function , frame .File , frame .Line )
173+ sp .SetTag ("caller" , callerDetails )
174+
175+ // Check params and call function
176+ f := reflect .ValueOf (fn )
177+ if f .Type ().NumIn () != len (params ) {
178+ e := fmt .Sprintf ("Incorrect number of parameters calling wrapped function %s" , name )
179+ panic (e )
180+ }
181+ inputs := make ([]reflect.Value , len (params ))
182+ for k , in := range params {
183+ inputs [k ] = reflect .ValueOf (in )
172184 }
173- defer sp .Finish ()
174185 return f .Call (inputs )
175186}
176187
177188// CreateChildSpan creates a new opentracing span adding tags for the span name and caller details.
178189// User must call defer `sp.Finish()`
179190func CreateChildSpan (ctx echo.Context , name string ) opentracing.Span {
180- pc , file , no , ok := runtime .Caller (1 )
181- details := runtime .FuncForPC (pc )
182191 parentSpan := opentracing .SpanFromContext (ctx .Request ().Context ())
183192 sp := opentracing .StartSpan (
184193 name ,
185194 opentracing .ChildOf (parentSpan .Context ()))
186- (opentracing.Tag {Key : "name" , Value : name }).Set (sp )
187- if ok {
188- callerDetails := fmt .Sprintf ("%s - %s#%d" , details .Name (), file , no )
189- (opentracing.Tag {Key : "caller" , Value : callerDetails }).Set (sp )
195+ sp .SetTag ("name" , name )
196+
197+ // Get caller function name, file and line
198+ pc := make ([]uintptr , 15 )
199+ n := runtime .Callers (2 , pc )
200+ frames := runtime .CallersFrames (pc [:n ])
201+ frame , _ := frames .Next ()
202+ callerDetails := fmt .Sprintf ("%s - %s#%d" , frame .Function , frame .File , frame .Line )
203+ sp .SetTag ("caller" , callerDetails )
190204
191- }
192205 return sp
193206}
207+
208+ // NewTracedRequest generates a new traced HTTP request with opentracing headers injected into it
209+ func NewTracedRequest (method string , url string , body io.Reader , span opentracing.Span ) (* http.Request , error ) {
210+ req , err := http .NewRequest (method , url , nil )
211+ if err != nil {
212+ panic (err .Error ())
213+ }
214+
215+ ext .SpanKindRPCClient .Set (span )
216+ ext .HTTPUrl .Set (span , url )
217+ ext .HTTPMethod .Set (span , method )
218+ span .Tracer ().Inject (span .Context (),
219+ opentracing .HTTPHeaders ,
220+ opentracing .HTTPHeadersCarrier (req .Header ))
221+
222+ return req , err
223+ }
0 commit comments