dubbo.apache.org/dubbo-go/v3@v3.1.1/filter/tracing/filter.go (about) 1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 // Package tracing provides tracing collection filter. 19 package tracing 20 21 import ( 22 "context" 23 ) 24 25 import ( 26 "github.com/opentracing/opentracing-go" 27 "github.com/opentracing/opentracing-go/log" 28 ) 29 30 import ( 31 "dubbo.apache.org/dubbo-go/v3/common/constant" 32 "dubbo.apache.org/dubbo-go/v3/common/extension" 33 "dubbo.apache.org/dubbo-go/v3/filter" 34 "dubbo.apache.org/dubbo-go/v3/protocol" 35 ) 36 37 // this should be executed before users set their own Tracer 38 func init() { 39 extension.SetFilter(constant.TracingFilterKey, newTracingFilter) 40 opentracing.SetGlobalTracer(opentracing.NoopTracer{}) 41 } 42 43 var ( 44 errorKey = "ErrorMsg" 45 successKey = "Success" 46 ) 47 48 // if you wish to using opentracing, please add the this filter into your filter attribute in your configure file. 49 // notice that this could be used in both client-side and server-side. 50 type tracingFilter struct{} 51 52 func (tf *tracingFilter) Invoke(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result { 53 var ( 54 spanCtx context.Context 55 span opentracing.Span 56 ) 57 operationName := invoker.GetURL().ServiceKey() + "#" + invocation.MethodName() 58 59 wiredCtx := ctx.Value(constant.TracingRemoteSpanCtx) 60 preSpan := opentracing.SpanFromContext(ctx) 61 62 if preSpan != nil { 63 // it means that someone already create a span to trace, so we use the span to be the parent span 64 span = opentracing.StartSpan(operationName, opentracing.ChildOf(preSpan.Context())) 65 spanCtx = opentracing.ContextWithSpan(ctx, span) 66 67 } else if wiredCtx != nil { 68 69 // it means that there has a remote span, usually from client side. so we use this as the parent 70 span = opentracing.StartSpan(operationName, opentracing.ChildOf(wiredCtx.(opentracing.SpanContext))) 71 spanCtx = opentracing.ContextWithSpan(ctx, span) 72 } else { 73 // it means that there is not any span, so we create a span as the root span. 74 span, spanCtx = opentracing.StartSpanFromContext(ctx, operationName) 75 } 76 77 defer func() { 78 span.Finish() 79 }() 80 81 result := invoker.Invoke(spanCtx, invocation) 82 span.SetTag(successKey, result.Error() == nil) 83 if result.Error() != nil { 84 span.LogFields(log.String(errorKey, result.Error().Error())) 85 } 86 return result 87 } 88 89 func (tf *tracingFilter) OnResponse(ctx context.Context, result protocol.Result, 90 invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result { 91 return result 92 } 93 94 var tracingFilterInstance filter.Filter 95 96 func newTracingFilter() filter.Filter { 97 if tracingFilterInstance == nil { 98 tracingFilterInstance = &tracingFilter{} 99 } 100 return tracingFilterInstance 101 }