google.golang.org/grpc@v1.72.2/stats/opentelemetry/csm/observability.go (about) 1 /* 2 * 3 * Copyright 2024 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * 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 19 package csm 20 21 import ( 22 "context" 23 "net/url" 24 25 "google.golang.org/grpc" 26 "google.golang.org/grpc/internal" 27 "google.golang.org/grpc/stats/opentelemetry" 28 otelinternal "google.golang.org/grpc/stats/opentelemetry/internal" 29 ) 30 31 // EnableObservability sets up CSM Observability for the binary globally. 32 // 33 // The CSM Stats Plugin is instantiated with local labels and metadata exchange 34 // labels pulled from the environment, and emits metadata exchange labels from 35 // the peer and local labels. Context timeouts do not trigger an error, but set 36 // certain labels to "unknown". 37 // 38 // This function is not thread safe, and should only be invoked once in main 39 // before any channels or servers are created. Returns a cleanup function to be 40 // deferred in main. 41 func EnableObservability(ctx context.Context, options opentelemetry.Options) func() { 42 csmPluginOption := newPluginOption(ctx) 43 clientSideOTelWithCSM := dialOptionWithCSMPluginOption(options, csmPluginOption) 44 clientSideOTel := opentelemetry.DialOption(options) 45 internal.AddGlobalPerTargetDialOptions.(func(opt any))(&perTargetDialOption{ 46 clientSideOTelWithCSM: clientSideOTelWithCSM, 47 clientSideOTel: clientSideOTel, 48 }) 49 50 serverSideOTelWithCSM := serverOptionWithCSMPluginOption(options, csmPluginOption) 51 internal.AddGlobalServerOptions.(func(opt ...grpc.ServerOption))(serverSideOTelWithCSM) 52 53 return func() { 54 internal.ClearGlobalServerOptions() 55 internal.ClearGlobalPerTargetDialOptions() 56 } 57 } 58 59 type perTargetDialOption struct { 60 clientSideOTelWithCSM grpc.DialOption 61 clientSideOTel grpc.DialOption 62 } 63 64 func (o *perTargetDialOption) DialOptionForTarget(parsedTarget url.URL) grpc.DialOption { 65 if determineTargetCSM(&parsedTarget) { 66 return o.clientSideOTelWithCSM 67 } 68 return o.clientSideOTel 69 } 70 71 func dialOptionWithCSMPluginOption(options opentelemetry.Options, po otelinternal.PluginOption) grpc.DialOption { 72 options.MetricsOptions.OptionalLabels = []string{"csm.service_name", "csm.service_namespace_name"} // Attach the two xDS Optional Labels for this component to not filter out. 73 return dialOptionSetCSM(options, po) 74 } 75 76 func dialOptionSetCSM(options opentelemetry.Options, po otelinternal.PluginOption) grpc.DialOption { 77 otelinternal.SetPluginOption.(func(options *opentelemetry.Options, po otelinternal.PluginOption))(&options, po) 78 return opentelemetry.DialOption(options) 79 } 80 81 func serverOptionWithCSMPluginOption(options opentelemetry.Options, po otelinternal.PluginOption) grpc.ServerOption { 82 otelinternal.SetPluginOption.(func(options *opentelemetry.Options, po otelinternal.PluginOption))(&options, po) 83 return opentelemetry.ServerOption(options) 84 }