dubbo.apache.org/dubbo-go/v3@v3.1.1/filter/otel/trace/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 trace 19 20 import ( 21 "context" 22 ) 23 24 import ( 25 "go.opentelemetry.io/otel" 26 "go.opentelemetry.io/otel/baggage" 27 "go.opentelemetry.io/otel/codes" 28 "go.opentelemetry.io/otel/propagation" 29 semconv "go.opentelemetry.io/otel/semconv/v1.7.0" 30 "go.opentelemetry.io/otel/trace" 31 ) 32 33 import ( 34 "dubbo.apache.org/dubbo-go/v3/common/constant" 35 "dubbo.apache.org/dubbo-go/v3/common/extension" 36 "dubbo.apache.org/dubbo-go/v3/filter" 37 "dubbo.apache.org/dubbo-go/v3/protocol" 38 ) 39 40 func init() { 41 // TODO: use single filter to simplify filter field in configuration 42 extension.SetFilter(constant.OTELServerTraceKey, func() filter.Filter { 43 return &otelServerFilter{ 44 Propagators: otel.GetTextMapPropagator(), 45 TracerProvider: otel.GetTracerProvider(), 46 } 47 }) 48 extension.SetFilter(constant.OTELClientTraceKey, func() filter.Filter { 49 return &otelClientFilter{ 50 Propagators: otel.GetTextMapPropagator(), 51 TracerProvider: otel.GetTracerProvider(), 52 } 53 }) 54 } 55 56 type otelServerFilter struct { 57 Propagators propagation.TextMapPropagator 58 TracerProvider trace.TracerProvider 59 } 60 61 func (f *otelServerFilter) OnResponse(ctx context.Context, result protocol.Result, invoker protocol.Invoker, protocol protocol.Invocation) protocol.Result { 62 return result 63 } 64 65 func (f *otelServerFilter) Invoke(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result { 66 attachments := invocation.Attachments() 67 bags, spanCtx := Extract(ctx, attachments, f.Propagators) 68 ctx = baggage.ContextWithBaggage(ctx, bags) 69 70 tracer := f.TracerProvider.Tracer( 71 constant.OtelPackageName, 72 trace.WithInstrumentationVersion(constant.OtelPackageVersion), 73 ) 74 75 ctx, span := tracer.Start( 76 trace.ContextWithRemoteSpanContext(ctx, spanCtx), 77 invocation.ActualMethodName(), 78 trace.WithSpanKind(trace.SpanKindServer), 79 trace.WithAttributes( 80 RPCSystemDubbo, 81 semconv.RPCServiceKey.String(invoker.GetURL().ServiceKey()), 82 semconv.RPCMethodKey.String(invocation.MethodName()), 83 ), 84 ) 85 defer span.End() 86 87 result := invoker.Invoke(ctx, invocation) 88 89 if result.Error() != nil { 90 span.SetStatus(codes.Error, result.Error().Error()) 91 } else { 92 span.SetStatus(codes.Ok, codes.Ok.String()) 93 } 94 return result 95 } 96 97 type otelClientFilter struct { 98 Propagators propagation.TextMapPropagator 99 TracerProvider trace.TracerProvider 100 } 101 102 func (f *otelClientFilter) OnResponse(ctx context.Context, result protocol.Result, invoker protocol.Invoker, protocol protocol.Invocation) protocol.Result { 103 return result 104 } 105 106 func (f *otelClientFilter) Invoke(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result { 107 tracer := f.TracerProvider.Tracer( 108 constant.OtelPackageName, 109 trace.WithInstrumentationVersion(constant.OtelPackageVersion), 110 ) 111 112 var span trace.Span 113 ctx, span = tracer.Start( 114 ctx, 115 invocation.ActualMethodName(), 116 trace.WithSpanKind(trace.SpanKindClient), 117 trace.WithAttributes( 118 RPCSystemDubbo, 119 semconv.RPCServiceKey.String(invoker.GetURL().ServiceKey()), 120 semconv.RPCMethodKey.String(invocation.MethodName()), 121 ), 122 ) 123 defer span.End() 124 125 attachments := invocation.Attachments() 126 if attachments == nil { 127 attachments = map[string]interface{}{} 128 } 129 Inject(ctx, attachments, f.Propagators) 130 for k, v := range attachments { 131 invocation.SetAttachment(k, v) 132 } 133 result := invoker.Invoke(ctx, invocation) 134 135 if result.Error() != nil { 136 span.SetStatus(codes.Error, result.Error().Error()) 137 } else { 138 span.SetStatus(codes.Ok, codes.Ok.String()) 139 } 140 return result 141 }