1// Copyright 2018, OpenCensus Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package ocgrpc
16
17import (
18	"context"
19
20	"google.golang.org/grpc/stats"
21
22	"go.opencensus.io/trace"
23)
24
25// ServerHandler implements gRPC stats.Handler recording OpenCensus stats and
26// traces. Use with gRPC servers.
27//
28// When installed (see Example), tracing metadata is read from inbound RPCs
29// by default. If no tracing metadata is present, or if the tracing metadata is
30// present but the SpanContext isn't sampled, then a new trace may be started
31// (as determined by Sampler).
32type ServerHandler struct {
33	// IsPublicEndpoint may be set to true to always start a new trace around
34	// each RPC. Any SpanContext in the RPC metadata will be added as a linked
35	// span instead of making it the parent of the span created around the
36	// server RPC.
37	//
38	// Be aware that if you leave this false (the default) on a public-facing
39	// server, callers will be able to send tracing metadata in gRPC headers
40	// and trigger traces in your backend.
41	IsPublicEndpoint bool
42
43	// StartOptions to use for to spans started around RPCs handled by this server.
44	//
45	// These will apply even if there is tracing metadata already
46	// present on the inbound RPC but the SpanContext is not sampled. This
47	// ensures that each service has some opportunity to be traced. If you would
48	// like to not add any additional traces for this gRPC service, set:
49	//
50	//   StartOptions.Sampler = trace.ProbabilitySampler(0.0)
51	//
52	// StartOptions.SpanKind will always be set to trace.SpanKindServer
53	// for spans started by this handler.
54	StartOptions trace.StartOptions
55}
56
57var _ stats.Handler = (*ServerHandler)(nil)
58
59// HandleConn exists to satisfy gRPC stats.Handler.
60func (s *ServerHandler) HandleConn(ctx context.Context, cs stats.ConnStats) {
61	// no-op
62}
63
64// TagConn exists to satisfy gRPC stats.Handler.
65func (s *ServerHandler) TagConn(ctx context.Context, cti *stats.ConnTagInfo) context.Context {
66	// no-op
67	return ctx
68}
69
70// HandleRPC implements per-RPC tracing and stats instrumentation.
71func (s *ServerHandler) HandleRPC(ctx context.Context, rs stats.RPCStats) {
72	traceHandleRPC(ctx, rs)
73	statsHandleRPC(ctx, rs)
74}
75
76// TagRPC implements per-RPC context management.
77func (s *ServerHandler) TagRPC(ctx context.Context, rti *stats.RPCTagInfo) context.Context {
78	ctx = s.traceTagRPC(ctx, rti)
79	ctx = s.statsTagRPC(ctx, rti)
80	return ctx
81}
82