2022-09-07 00:53:49 +00:00
|
|
|
// Copyright 2016-2022, Pulumi Corporation.
|
2018-05-22 19:43:36 +00:00
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
2017-11-19 16:08:22 +00:00
|
|
|
|
2017-11-09 01:08:51 +00:00
|
|
|
package rpcutil
|
|
|
|
|
|
|
|
import (
|
2022-09-21 14:56:59 +00:00
|
|
|
"os"
|
|
|
|
|
2017-11-09 01:08:51 +00:00
|
|
|
"github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc"
|
|
|
|
opentracing "github.com/opentracing/opentracing-go"
|
2022-09-21 14:56:59 +00:00
|
|
|
"github.com/pulumi/pulumi/sdk/v3/go/common/util/cmdutil"
|
2017-11-09 01:08:51 +00:00
|
|
|
"google.golang.org/grpc"
|
|
|
|
)
|
|
|
|
|
2022-11-01 15:15:09 +00:00
|
|
|
// Configures interceptors to propagate OpenTracing metadata through headers. If parentSpan is non-nil, it becomes the
|
|
|
|
// default parent for orphan spans.
|
|
|
|
func OpenTracingServerInterceptorOptions(parentSpan opentracing.Span, options ...otgrpc.Option) []grpc.ServerOption {
|
|
|
|
return []grpc.ServerOption{
|
|
|
|
grpc.ChainUnaryInterceptor(OpenTracingServerInterceptor(parentSpan, options...)),
|
|
|
|
grpc.ChainStreamInterceptor(OpenTracingStreamServerInterceptor(parentSpan, options...)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-07 00:53:49 +00:00
|
|
|
// OpenTracingServerInterceptor provides a default gRPC server
|
|
|
|
// interceptor for emitting tracing to the global OpenTracing tracer.
|
2021-06-17 21:46:05 +00:00
|
|
|
func OpenTracingServerInterceptor(parentSpan opentracing.Span, options ...otgrpc.Option) grpc.UnaryServerInterceptor {
|
2022-09-21 14:56:59 +00:00
|
|
|
options = append(options, logPayloads()...)
|
2022-09-07 00:53:49 +00:00
|
|
|
tracer := opentracing.GlobalTracer()
|
2021-06-17 21:46:05 +00:00
|
|
|
|
2022-09-07 00:53:49 +00:00
|
|
|
if parentSpan != nil {
|
|
|
|
tracer = &reparentingTracer{parentSpan.Context(), tracer}
|
2019-09-16 21:16:43 +00:00
|
|
|
}
|
|
|
|
|
2022-09-07 00:53:49 +00:00
|
|
|
return otgrpc.OpenTracingServerInterceptor(tracer, options...)
|
2017-11-09 01:08:51 +00:00
|
|
|
}
|
|
|
|
|
2022-10-09 14:58:33 +00:00
|
|
|
// OpenTracingStreamServerInterceptor is OpenTracingServerInterceptor for instrumenting streaming gRPC calls.
|
2022-09-12 21:42:27 +00:00
|
|
|
func OpenTracingStreamServerInterceptor(parentSpan opentracing.Span,
|
2023-03-03 16:36:39 +00:00
|
|
|
options ...otgrpc.Option,
|
|
|
|
) grpc.StreamServerInterceptor {
|
2022-09-21 14:56:59 +00:00
|
|
|
options = append(options, logPayloads()...)
|
2022-09-12 21:42:27 +00:00
|
|
|
tracer := opentracing.GlobalTracer()
|
|
|
|
|
|
|
|
if parentSpan != nil {
|
|
|
|
tracer = &reparentingTracer{parentSpan.Context(), tracer}
|
|
|
|
}
|
|
|
|
|
|
|
|
return otgrpc.OpenTracingStreamServerInterceptor(tracer, options...)
|
|
|
|
}
|
|
|
|
|
2017-11-09 01:08:51 +00:00
|
|
|
// OpenTracingClientInterceptor provides a default gRPC client interceptor for emitting tracing to the global
|
|
|
|
// OpenTracing tracer.
|
2021-06-17 21:46:05 +00:00
|
|
|
func OpenTracingClientInterceptor(options ...otgrpc.Option) grpc.UnaryClientInterceptor {
|
2022-09-21 14:56:59 +00:00
|
|
|
options = append(append(options,
|
2019-09-16 21:16:43 +00:00
|
|
|
// Do not trace calls to the empty method
|
|
|
|
otgrpc.IncludingSpans(func(_ opentracing.SpanContext, method string, _, _ interface{}) bool {
|
|
|
|
return method != ""
|
2022-09-21 14:56:59 +00:00
|
|
|
})), logPayloads()...)
|
2021-06-17 21:46:05 +00:00
|
|
|
return otgrpc.OpenTracingClientInterceptor(opentracing.GlobalTracer(), options...)
|
2017-11-09 01:08:51 +00:00
|
|
|
}
|
2022-09-07 00:53:49 +00:00
|
|
|
|
2022-10-09 14:58:33 +00:00
|
|
|
// OpenTracingStreamClientInterceptor is OpenTracingClientInterceptor for streaming gRPC calls.
|
2022-09-12 21:42:27 +00:00
|
|
|
func OpenTracingStreamClientInterceptor(options ...otgrpc.Option) grpc.StreamClientInterceptor {
|
2022-09-21 14:56:59 +00:00
|
|
|
options = append(append(options,
|
2022-09-12 21:42:27 +00:00
|
|
|
// Do not trace calls to the empty method
|
|
|
|
otgrpc.IncludingSpans(func(_ opentracing.SpanContext, method string, _, _ interface{}) bool {
|
|
|
|
return method != ""
|
2022-09-21 14:56:59 +00:00
|
|
|
})), logPayloads()...)
|
2022-09-12 21:42:27 +00:00
|
|
|
return otgrpc.OpenTracingStreamClientInterceptor(opentracing.GlobalTracer(), options...)
|
|
|
|
}
|
|
|
|
|
2022-11-01 15:15:09 +00:00
|
|
|
// Configures gRPC clients with OpenTracing interceptors.
|
|
|
|
func OpenTracingInterceptorDialOptions(opts ...otgrpc.Option) []grpc.DialOption {
|
|
|
|
return []grpc.DialOption{
|
|
|
|
grpc.WithChainUnaryInterceptor(OpenTracingClientInterceptor(opts...)),
|
|
|
|
grpc.WithChainStreamInterceptor(OpenTracingStreamClientInterceptor(opts...)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-07 00:53:49 +00:00
|
|
|
// Wraps an opentracing.Tracer to reparent orphan traces with a given
|
|
|
|
// default parent span.
|
|
|
|
type reparentingTracer struct {
|
|
|
|
parentSpanContext opentracing.SpanContext
|
|
|
|
underlying opentracing.Tracer
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *reparentingTracer) StartSpan(operationName string, opts ...opentracing.StartSpanOption) opentracing.Span {
|
|
|
|
if !t.hasChildOf(opts...) {
|
|
|
|
opts = append(opts, opentracing.ChildOf(t.parentSpanContext))
|
|
|
|
}
|
|
|
|
return t.underlying.StartSpan(operationName, opts...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *reparentingTracer) Inject(sm opentracing.SpanContext, format interface{}, carrier interface{}) error {
|
|
|
|
return t.underlying.Inject(sm, format, carrier)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *reparentingTracer) Extract(format interface{}, carrier interface{}) (opentracing.SpanContext, error) {
|
|
|
|
return t.underlying.Extract(format, carrier)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *reparentingTracer) packOptions(opts ...opentracing.StartSpanOption) opentracing.StartSpanOptions {
|
|
|
|
sso := opentracing.StartSpanOptions{}
|
|
|
|
for _, o := range opts {
|
|
|
|
o.Apply(&sso)
|
|
|
|
}
|
|
|
|
return sso
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *reparentingTracer) hasChildOf(opts ...opentracing.StartSpanOption) bool {
|
|
|
|
for _, ref := range t.packOptions(opts...).References {
|
|
|
|
if ref.Type == opentracing.ChildOfRef {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ opentracing.Tracer = &reparentingTracer{}
|
2022-09-21 14:56:59 +00:00
|
|
|
|
2022-09-22 14:30:13 +00:00
|
|
|
// Option to log payloads in trace spans. Default is on. Can be
|
2022-09-21 14:56:59 +00:00
|
|
|
// disabled by setting an env var to reduce tracing overhead.
|
|
|
|
func logPayloads() []otgrpc.Option {
|
|
|
|
res := []otgrpc.Option{}
|
|
|
|
if !cmdutil.IsTruthy(os.Getenv("PULUMI_TRACING_NO_PAYLOADS")) {
|
|
|
|
res = append(res, otgrpc.LogPayloads())
|
|
|
|
}
|
|
|
|
return res
|
|
|
|
}
|