rebase: bump google.golang.org/grpc from 1.49.0 to 1.50.1

Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.49.0 to 1.50.1.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.49.0...v1.50.1)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
dependabot[bot] 2022-11-08 08:23:05 +00:00 committed by mergify[bot]
parent fe13fff9fa
commit 076816d26e
24 changed files with 425 additions and 179 deletions

2
go.mod
View File

@ -30,7 +30,7 @@ require (
golang.org/x/crypto v0.1.0 golang.org/x/crypto v0.1.0
golang.org/x/net v0.1.0 golang.org/x/net v0.1.0
golang.org/x/sys v0.1.0 golang.org/x/sys v0.1.0
google.golang.org/grpc v1.49.0 google.golang.org/grpc v1.50.1
google.golang.org/protobuf v1.28.0 google.golang.org/protobuf v1.28.0
k8s.io/api v0.25.3 k8s.io/api v0.25.3
k8s.io/apimachinery v0.25.3 k8s.io/apimachinery v0.25.3

4
go.sum
View File

@ -1794,8 +1794,8 @@ google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzI
google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.49.0 h1:WTLtQzmQori5FUH25Pq4WT22oCsv8USpQ+F6rqtsmxw= google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY=
google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=

View File

@ -244,7 +244,7 @@ type DoneInfo struct {
// ServerLoad is the load received from server. It's usually sent as part of // ServerLoad is the load received from server. It's usually sent as part of
// trailing metadata. // trailing metadata.
// //
// The only supported type now is *orca_v1.LoadReport. // The only supported type now is *orca_v3.LoadReport.
ServerLoad interface{} ServerLoad interface{}
} }

View File

@ -22,7 +22,7 @@
package roundrobin package roundrobin
import ( import (
"sync" "sync/atomic"
"google.golang.org/grpc/balancer" "google.golang.org/grpc/balancer"
"google.golang.org/grpc/balancer/base" "google.golang.org/grpc/balancer/base"
@ -60,7 +60,7 @@ func (*rrPickerBuilder) Build(info base.PickerBuildInfo) balancer.Picker {
// Start at a random index, as the same RR balancer rebuilds a new // Start at a random index, as the same RR balancer rebuilds a new
// picker when SubConn states change, and we don't want to apply excess // picker when SubConn states change, and we don't want to apply excess
// load to the first server in the list. // load to the first server in the list.
next: grpcrand.Intn(len(scs)), next: uint32(grpcrand.Intn(len(scs))),
} }
} }
@ -69,15 +69,13 @@ type rrPicker struct {
// created. The slice is immutable. Each Get() will do a round robin // created. The slice is immutable. Each Get() will do a round robin
// selection from it and return the selected SubConn. // selection from it and return the selected SubConn.
subConns []balancer.SubConn subConns []balancer.SubConn
next uint32
mu sync.Mutex
next int
} }
func (p *rrPicker) Pick(balancer.PickInfo) (balancer.PickResult, error) { func (p *rrPicker) Pick(balancer.PickInfo) (balancer.PickResult, error) {
p.mu.Lock() subConnsLen := uint32(len(p.subConns))
sc := p.subConns[p.next] nextIndex := atomic.AddUint32(&p.next, 1)
p.next = (p.next + 1) % len(p.subConns)
p.mu.Unlock() sc := p.subConns[nextIndex%subConnsLen]
return balancer.PickResult{SubConn: sc}, nil return balancer.PickResult{SubConn: sc}, nil
} }

View File

@ -29,6 +29,7 @@ import (
"google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/internal" "google.golang.org/grpc/internal"
internalbackoff "google.golang.org/grpc/internal/backoff" internalbackoff "google.golang.org/grpc/internal/backoff"
"google.golang.org/grpc/internal/binarylog"
"google.golang.org/grpc/internal/transport" "google.golang.org/grpc/internal/transport"
"google.golang.org/grpc/keepalive" "google.golang.org/grpc/keepalive"
"google.golang.org/grpc/resolver" "google.golang.org/grpc/resolver"
@ -36,12 +37,13 @@ import (
) )
func init() { func init() {
internal.AddExtraDialOptions = func(opt ...DialOption) { internal.AddGlobalDialOptions = func(opt ...DialOption) {
extraDialOptions = append(extraDialOptions, opt...) extraDialOptions = append(extraDialOptions, opt...)
} }
internal.ClearExtraDialOptions = func() { internal.ClearGlobalDialOptions = func() {
extraDialOptions = nil extraDialOptions = nil
} }
internal.WithBinaryLogger = withBinaryLogger
} }
// dialOptions configure a Dial call. dialOptions are set by the DialOption // dialOptions configure a Dial call. dialOptions are set by the DialOption
@ -61,6 +63,7 @@ type dialOptions struct {
timeout time.Duration timeout time.Duration
scChan <-chan ServiceConfig scChan <-chan ServiceConfig
authority string authority string
binaryLogger binarylog.Logger
copts transport.ConnectOptions copts transport.ConnectOptions
callOptions []CallOption callOptions []CallOption
channelzParentID *channelz.Identifier channelzParentID *channelz.Identifier
@ -401,6 +404,14 @@ func WithStatsHandler(h stats.Handler) DialOption {
}) })
} }
// withBinaryLogger returns a DialOption that specifies the binary logger for
// this ClientConn.
func withBinaryLogger(bl binarylog.Logger) DialOption {
return newFuncDialOption(func(o *dialOptions) {
o.binaryLogger = bl
})
}
// FailOnNonTempDialError returns a DialOption that specifies if gRPC fails on // FailOnNonTempDialError returns a DialOption that specifies if gRPC fails on
// non-temporary dial errors. If f is true, and dialer returns a non-temporary // non-temporary dial errors. If f is true, and dialer returns a non-temporary
// error, gRPC will fail the connection to the network address and won't try to // error, gRPC will fail the connection to the network address and won't try to

View File

@ -1,3 +1,20 @@
// Copyright 2015 The gRPC Authors
//
// 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.
// The canonical version of this proto can be found at
// https://github.com/grpc/grpc-proto/blob/master/grpc/health/v1/health.proto
// Code generated by protoc-gen-go-grpc. DO NOT EDIT. // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions: // versions:
// - protoc-gen-go-grpc v1.2.0 // - protoc-gen-go-grpc v1.2.0

View File

@ -37,7 +37,7 @@ type Logger interface {
// binLogger is the global binary logger for the binary. One of this should be // binLogger is the global binary logger for the binary. One of this should be
// built at init time from the configuration (environment variable or flags). // built at init time from the configuration (environment variable or flags).
// //
// It is used to get a methodLogger for each individual method. // It is used to get a MethodLogger for each individual method.
var binLogger Logger var binLogger Logger
var grpclogLogger = grpclog.Component("binarylog") var grpclogLogger = grpclog.Component("binarylog")
@ -56,11 +56,11 @@ func GetLogger() Logger {
return binLogger return binLogger
} }
// GetMethodLogger returns the methodLogger for the given methodName. // GetMethodLogger returns the MethodLogger for the given methodName.
// //
// methodName should be in the format of "/service/method". // methodName should be in the format of "/service/method".
// //
// Each methodLogger returned by this method is a new instance. This is to // Each MethodLogger returned by this method is a new instance. This is to
// generate sequence id within the call. // generate sequence id within the call.
func GetMethodLogger(methodName string) MethodLogger { func GetMethodLogger(methodName string) MethodLogger {
if binLogger == nil { if binLogger == nil {
@ -117,7 +117,7 @@ func (l *logger) setDefaultMethodLogger(ml *MethodLoggerConfig) error {
// Set method logger for "service/*". // Set method logger for "service/*".
// //
// New methodLogger with same service overrides the old one. // New MethodLogger with same service overrides the old one.
func (l *logger) setServiceMethodLogger(service string, ml *MethodLoggerConfig) error { func (l *logger) setServiceMethodLogger(service string, ml *MethodLoggerConfig) error {
if _, ok := l.config.Services[service]; ok { if _, ok := l.config.Services[service]; ok {
return fmt.Errorf("conflicting service rules for service %v found", service) return fmt.Errorf("conflicting service rules for service %v found", service)
@ -131,7 +131,7 @@ func (l *logger) setServiceMethodLogger(service string, ml *MethodLoggerConfig)
// Set method logger for "service/method". // Set method logger for "service/method".
// //
// New methodLogger with same method overrides the old one. // New MethodLogger with same method overrides the old one.
func (l *logger) setMethodMethodLogger(method string, ml *MethodLoggerConfig) error { func (l *logger) setMethodMethodLogger(method string, ml *MethodLoggerConfig) error {
if _, ok := l.config.Blacklist[method]; ok { if _, ok := l.config.Blacklist[method]; ok {
return fmt.Errorf("conflicting blacklist rules for method %v found", method) return fmt.Errorf("conflicting blacklist rules for method %v found", method)
@ -161,11 +161,11 @@ func (l *logger) setBlacklist(method string) error {
return nil return nil
} }
// getMethodLogger returns the methodLogger for the given methodName. // getMethodLogger returns the MethodLogger for the given methodName.
// //
// methodName should be in the format of "/service/method". // methodName should be in the format of "/service/method".
// //
// Each methodLogger returned by this method is a new instance. This is to // Each MethodLogger returned by this method is a new instance. This is to
// generate sequence id within the call. // generate sequence id within the call.
func (l *logger) GetMethodLogger(methodName string) MethodLogger { func (l *logger) GetMethodLogger(methodName string) MethodLogger {
s, m, err := grpcutil.ParseMethod(methodName) s, m, err := grpcutil.ParseMethod(methodName)
@ -174,16 +174,16 @@ func (l *logger) GetMethodLogger(methodName string) MethodLogger {
return nil return nil
} }
if ml, ok := l.config.Methods[s+"/"+m]; ok { if ml, ok := l.config.Methods[s+"/"+m]; ok {
return newMethodLogger(ml.Header, ml.Message) return NewTruncatingMethodLogger(ml.Header, ml.Message)
} }
if _, ok := l.config.Blacklist[s+"/"+m]; ok { if _, ok := l.config.Blacklist[s+"/"+m]; ok {
return nil return nil
} }
if ml, ok := l.config.Services[s]; ok { if ml, ok := l.config.Services[s]; ok {
return newMethodLogger(ml.Header, ml.Message) return NewTruncatingMethodLogger(ml.Header, ml.Message)
} }
if l.config.All == nil { if l.config.All == nil {
return nil return nil
} }
return newMethodLogger(l.config.All.Header, l.config.All.Message) return NewTruncatingMethodLogger(l.config.All.Header, l.config.All.Message)
} }

View File

@ -57,7 +57,7 @@ func NewLoggerFromConfigString(s string) Logger {
return l return l
} }
// fillMethodLoggerWithConfigString parses config, creates methodLogger and adds // fillMethodLoggerWithConfigString parses config, creates TruncatingMethodLogger and adds
// it to the right map in the logger. // it to the right map in the logger.
func (l *logger) fillMethodLoggerWithConfigString(config string) error { func (l *logger) fillMethodLoggerWithConfigString(config string) error {
// "" is invalid. // "" is invalid.

View File

@ -52,7 +52,9 @@ type MethodLogger interface {
Log(LogEntryConfig) Log(LogEntryConfig)
} }
type methodLogger struct { // TruncatingMethodLogger is a method logger that truncates headers and messages
// based on configured fields.
type TruncatingMethodLogger struct {
headerMaxLen, messageMaxLen uint64 headerMaxLen, messageMaxLen uint64
callID uint64 callID uint64
@ -61,8 +63,9 @@ type methodLogger struct {
sink Sink // TODO(blog): make this plugable. sink Sink // TODO(blog): make this plugable.
} }
func newMethodLogger(h, m uint64) *methodLogger { // NewTruncatingMethodLogger returns a new truncating method logger.
return &methodLogger{ func NewTruncatingMethodLogger(h, m uint64) *TruncatingMethodLogger {
return &TruncatingMethodLogger{
headerMaxLen: h, headerMaxLen: h,
messageMaxLen: m, messageMaxLen: m,
@ -75,8 +78,8 @@ func newMethodLogger(h, m uint64) *methodLogger {
// Build is an internal only method for building the proto message out of the // Build is an internal only method for building the proto message out of the
// input event. It's made public to enable other library to reuse as much logic // input event. It's made public to enable other library to reuse as much logic
// in methodLogger as possible. // in TruncatingMethodLogger as possible.
func (ml *methodLogger) Build(c LogEntryConfig) *pb.GrpcLogEntry { func (ml *TruncatingMethodLogger) Build(c LogEntryConfig) *pb.GrpcLogEntry {
m := c.toProto() m := c.toProto()
timestamp, _ := ptypes.TimestampProto(time.Now()) timestamp, _ := ptypes.TimestampProto(time.Now())
m.Timestamp = timestamp m.Timestamp = timestamp
@ -95,11 +98,11 @@ func (ml *methodLogger) Build(c LogEntryConfig) *pb.GrpcLogEntry {
} }
// Log creates a proto binary log entry, and logs it to the sink. // Log creates a proto binary log entry, and logs it to the sink.
func (ml *methodLogger) Log(c LogEntryConfig) { func (ml *TruncatingMethodLogger) Log(c LogEntryConfig) {
ml.sink.Write(ml.Build(c)) ml.sink.Write(ml.Build(c))
} }
func (ml *methodLogger) truncateMetadata(mdPb *pb.Metadata) (truncated bool) { func (ml *TruncatingMethodLogger) truncateMetadata(mdPb *pb.Metadata) (truncated bool) {
if ml.headerMaxLen == maxUInt { if ml.headerMaxLen == maxUInt {
return false return false
} }
@ -129,7 +132,7 @@ func (ml *methodLogger) truncateMetadata(mdPb *pb.Metadata) (truncated bool) {
return truncated return truncated
} }
func (ml *methodLogger) truncateMessage(msgPb *pb.Message) (truncated bool) { func (ml *TruncatingMethodLogger) truncateMessage(msgPb *pb.Message) (truncated bool) {
if ml.messageMaxLen == maxUInt { if ml.messageMaxLen == maxUInt {
return false return false
} }

View File

@ -0,0 +1,36 @@
/*
*
* Copyright 2022 gRPC authors.
*
* 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.
*
*/
package envconfig
import "os"
const (
envObservabilityConfig = "GRPC_GCP_OBSERVABILITY_CONFIG"
envObservabilityConfigFile = "GRPC_GCP_OBSERVABILITY_CONFIG_FILE"
)
var (
// ObservabilityConfig is the json configuration for the gcp/observability
// package specified directly in the envObservabilityConfig env var.
ObservabilityConfig = os.Getenv(envObservabilityConfig)
// ObservabilityConfigFile is the json configuration for the
// gcp/observability specified in a file with the location specified in
// envObservabilityConfigFile env var.
ObservabilityConfigFile = os.Getenv(envObservabilityConfigFile)
)

View File

@ -41,6 +41,7 @@ const (
clientSideSecuritySupportEnv = "GRPC_XDS_EXPERIMENTAL_SECURITY_SUPPORT" clientSideSecuritySupportEnv = "GRPC_XDS_EXPERIMENTAL_SECURITY_SUPPORT"
aggregateAndDNSSupportEnv = "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER" aggregateAndDNSSupportEnv = "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER"
rbacSupportEnv = "GRPC_XDS_EXPERIMENTAL_RBAC" rbacSupportEnv = "GRPC_XDS_EXPERIMENTAL_RBAC"
outlierDetectionSupportEnv = "GRPC_EXPERIMENTAL_ENABLE_OUTLIER_DETECTION"
federationEnv = "GRPC_EXPERIMENTAL_XDS_FEDERATION" federationEnv = "GRPC_EXPERIMENTAL_XDS_FEDERATION"
rlsInXDSEnv = "GRPC_EXPERIMENTAL_XDS_RLS_LB" rlsInXDSEnv = "GRPC_EXPERIMENTAL_XDS_RLS_LB"
@ -83,9 +84,9 @@ var (
// "GRPC_XDS_EXPERIMENTAL_RBAC" to "false". // "GRPC_XDS_EXPERIMENTAL_RBAC" to "false".
XDSRBAC = !strings.EqualFold(os.Getenv(rbacSupportEnv), "false") XDSRBAC = !strings.EqualFold(os.Getenv(rbacSupportEnv), "false")
// XDSOutlierDetection indicates whether outlier detection support is // XDSOutlierDetection indicates whether outlier detection support is
// enabled, which can be enabled by setting the environment variable // enabled, which can be disabled by setting the environment variable
// "GRPC_EXPERIMENTAL_ENABLE_OUTLIER_DETECTION" to "true". // "GRPC_EXPERIMENTAL_ENABLE_OUTLIER_DETECTION" to "false".
XDSOutlierDetection = false XDSOutlierDetection = !strings.EqualFold(os.Getenv(outlierDetectionSupportEnv), "false")
// XDSFederation indicates whether federation support is enabled. // XDSFederation indicates whether federation support is enabled.
XDSFederation = strings.EqualFold(os.Getenv(federationEnv), "true") XDSFederation = strings.EqualFold(os.Getenv(federationEnv), "true")

View File

@ -52,6 +52,13 @@ func Intn(n int) int {
return r.Intn(n) return r.Intn(n)
} }
// Int31n implements rand.Int31n on the grpcrand global source.
func Int31n(n int32) int32 {
mu.Lock()
defer mu.Unlock()
return r.Int31n(n)
}
// Float64 implements rand.Float64 on the grpcrand global source. // Float64 implements rand.Float64 on the grpcrand global source.
func Float64() float64 { func Float64() float64 {
mu.Lock() mu.Lock()

View File

@ -63,20 +63,30 @@ var (
// xDS-enabled server invokes this method on a grpc.Server when a particular // xDS-enabled server invokes this method on a grpc.Server when a particular
// listener moves to "not-serving" mode. // listener moves to "not-serving" mode.
DrainServerTransports interface{} // func(*grpc.Server, string) DrainServerTransports interface{} // func(*grpc.Server, string)
// AddExtraServerOptions adds an array of ServerOption that will be // AddGlobalServerOptions adds an array of ServerOption that will be
// effective globally for newly created servers. The priority will be: 1. // effective globally for newly created servers. The priority will be: 1.
// user-provided; 2. this method; 3. default values. // user-provided; 2. this method; 3. default values.
AddExtraServerOptions interface{} // func(opt ...ServerOption) AddGlobalServerOptions interface{} // func(opt ...ServerOption)
// ClearExtraServerOptions clears the array of extra ServerOption. This // ClearGlobalServerOptions clears the array of extra ServerOption. This
// method is useful in testing and benchmarking. // method is useful in testing and benchmarking.
ClearExtraServerOptions func() ClearGlobalServerOptions func()
// AddExtraDialOptions adds an array of DialOption that will be effective // AddGlobalDialOptions adds an array of DialOption that will be effective
// globally for newly created client channels. The priority will be: 1. // globally for newly created client channels. The priority will be: 1.
// user-provided; 2. this method; 3. default values. // user-provided; 2. this method; 3. default values.
AddExtraDialOptions interface{} // func(opt ...DialOption) AddGlobalDialOptions interface{} // func(opt ...DialOption)
// ClearExtraDialOptions clears the array of extra DialOption. This // ClearGlobalDialOptions clears the array of extra DialOption. This
// method is useful in testing and benchmarking. // method is useful in testing and benchmarking.
ClearExtraDialOptions func() ClearGlobalDialOptions func()
// JoinServerOptions combines the server options passed as arguments into a
// single server option.
JoinServerOptions interface{} // func(...grpc.ServerOption) grpc.ServerOption
// WithBinaryLogger returns a DialOption that specifies the binary logger
// for a ClientConn.
WithBinaryLogger interface{} // func(binarylog.Logger) grpc.DialOption
// BinaryLogger returns a ServerOption that can set the binary logger for a
// server.
BinaryLogger interface{} // func(binarylog.Logger) grpc.ServerOption
// NewXDSResolverWithConfigForTesting creates a new xds resolver builder using // NewXDSResolverWithConfigForTesting creates a new xds resolver builder using
// the provided xds bootstrap config instead of the global configuration from // the provided xds bootstrap config instead of the global configuration from
@ -117,22 +127,6 @@ var (
// //
// TODO: Remove this function once the RBAC env var is removed. // TODO: Remove this function once the RBAC env var is removed.
UnregisterRBACHTTPFilterForTesting func() UnregisterRBACHTTPFilterForTesting func()
// RegisterOutlierDetectionBalancerForTesting registers the Outlier
// Detection Balancer for testing purposes, regardless of the Outlier
// Detection environment variable.
//
// TODO: Remove this function once the Outlier Detection env var is removed.
RegisterOutlierDetectionBalancerForTesting func()
// UnregisterOutlierDetectionBalancerForTesting unregisters the Outlier
// Detection Balancer for testing purposes. This is needed because there is
// no way to unregister the Outlier Detection Balancer after registering it
// solely for testing purposes using
// RegisterOutlierDetectionBalancerForTesting().
//
// TODO: Remove this function once the Outlier Detection env var is removed.
UnregisterOutlierDetectionBalancerForTesting func()
) )
// HealthChecker defines the signature of the client-side LB channel health checking function. // HealthChecker defines the signature of the client-side LB channel health checking function.

View File

@ -49,8 +49,9 @@ func (b *builder) Build(target resolver.Target, cc resolver.ClientConn, _ resolv
} }
addr := resolver.Address{Addr: endpoint} addr := resolver.Address{Addr: endpoint}
if b.scheme == unixAbstractScheme { if b.scheme == unixAbstractScheme {
// prepend "\x00" to address for unix-abstract // We can not prepend \0 as c++ gRPC does, as in Golang '@' is used to signify we do
addr.Addr = "\x00" + addr.Addr // not want trailing \0 in address.
addr.Addr = "@" + addr.Addr
} }
cc.UpdateState(resolver.State{Addresses: []resolver.Address{networktype.Set(addr, "unix")}}) cc.UpdateState(resolver.State{Addresses: []resolver.Address{networktype.Set(addr, "unix")}})
return &nopResolver{}, nil return &nopResolver{}, nil

View File

@ -886,9 +886,9 @@ func (l *loopyWriter) processData() (bool, error) {
dataItem := str.itl.peek().(*dataFrame) // Peek at the first data item this stream. dataItem := str.itl.peek().(*dataFrame) // Peek at the first data item this stream.
// A data item is represented by a dataFrame, since it later translates into // A data item is represented by a dataFrame, since it later translates into
// multiple HTTP2 data frames. // multiple HTTP2 data frames.
// Every dataFrame has two buffers; h that keeps grpc-message header and d that is acutal data. // Every dataFrame has two buffers; h that keeps grpc-message header and d that is actual data.
// As an optimization to keep wire traffic low, data from d is copied to h to make as big as the // As an optimization to keep wire traffic low, data from d is copied to h to make as big as the
// maximum possilbe HTTP2 frame size. // maximum possible HTTP2 frame size.
if len(dataItem.h) == 0 && len(dataItem.d) == 0 { // Empty data frame if len(dataItem.h) == 0 && len(dataItem.d) == 0 { // Empty data frame
// Client sends out empty data frame with endStream = true // Client sends out empty data frame with endStream = true

View File

@ -326,6 +326,8 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts
keepaliveEnabled: keepaliveEnabled, keepaliveEnabled: keepaliveEnabled,
bufferPool: newBufferPool(), bufferPool: newBufferPool(),
} }
// Add peer information to the http2client context.
t.ctx = peer.NewContext(t.ctx, t.getPeer())
if md, ok := addr.Metadata.(*metadata.MD); ok { if md, ok := addr.Metadata.(*metadata.MD); ok {
t.md = *md t.md = *md
@ -469,7 +471,7 @@ func (t *http2Client) newStream(ctx context.Context, callHdr *CallHdr) *Stream {
func (t *http2Client) getPeer() *peer.Peer { func (t *http2Client) getPeer() *peer.Peer {
return &peer.Peer{ return &peer.Peer{
Addr: t.remoteAddr, Addr: t.remoteAddr,
AuthInfo: t.authInfo, AuthInfo: t.authInfo, // Can be nil
} }
} }
@ -1230,18 +1232,29 @@ func (t *http2Client) handleGoAway(f *http2.GoAwayFrame) {
if upperLimit == 0 { // This is the first GoAway Frame. if upperLimit == 0 { // This is the first GoAway Frame.
upperLimit = math.MaxUint32 // Kill all streams after the GoAway ID. upperLimit = math.MaxUint32 // Kill all streams after the GoAway ID.
} }
t.prevGoAwayID = id
if len(t.activeStreams) == 0 {
t.mu.Unlock()
t.Close(connectionErrorf(true, nil, "received goaway and there are no active streams"))
return
}
streamsToClose := make([]*Stream, 0)
for streamID, stream := range t.activeStreams { for streamID, stream := range t.activeStreams {
if streamID > id && streamID <= upperLimit { if streamID > id && streamID <= upperLimit {
// The stream was unprocessed by the server. // The stream was unprocessed by the server.
atomic.StoreUint32(&stream.unprocessed, 1) if streamID > id && streamID <= upperLimit {
t.closeStream(stream, errStreamDrain, false, http2.ErrCodeNo, statusGoAway, nil, false) atomic.StoreUint32(&stream.unprocessed, 1)
streamsToClose = append(streamsToClose, stream)
}
} }
} }
t.prevGoAwayID = id
active := len(t.activeStreams)
t.mu.Unlock() t.mu.Unlock()
if active == 0 { // Called outside t.mu because closeStream can take controlBuf's mu, which
t.Close(connectionErrorf(true, nil, "received goaway and there are no active streams")) // could induce deadlock and is not allowed.
for _, stream := range streamsToClose {
t.closeStream(stream, errStreamDrain, false, http2.ErrCodeNo, statusGoAway, nil, false)
} }
} }

View File

@ -265,6 +265,9 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport,
czData: new(channelzData), czData: new(channelzData),
bufferPool: newBufferPool(), bufferPool: newBufferPool(),
} }
// Add peer information to the http2server context.
t.ctx = peer.NewContext(t.ctx, t.getPeer())
t.controlBuf = newControlBuffer(t.done) t.controlBuf = newControlBuffer(t.done)
if dynamicWindow { if dynamicWindow {
t.bdpEst = &bdpEstimator{ t.bdpEst = &bdpEstimator{
@ -485,14 +488,7 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(
} else { } else {
s.ctx, s.cancel = context.WithCancel(t.ctx) s.ctx, s.cancel = context.WithCancel(t.ctx)
} }
pr := &peer.Peer{
Addr: t.remoteAddr,
}
// Attach Auth info if there is any.
if t.authInfo != nil {
pr.AuthInfo = t.authInfo
}
s.ctx = peer.NewContext(s.ctx, pr)
// Attach the received metadata to the context. // Attach the received metadata to the context.
if len(mdata) > 0 { if len(mdata) > 0 {
s.ctx = metadata.NewIncomingContext(s.ctx, mdata) s.ctx = metadata.NewIncomingContext(s.ctx, mdata)
@ -1416,6 +1412,13 @@ func (t *http2Server) getOutFlowWindow() int64 {
} }
} }
func (t *http2Server) getPeer() *peer.Peer {
return &peer.Peer{
Addr: t.remoteAddr,
AuthInfo: t.authInfo, // Can be nil
}
}
func getJitter(v time.Duration) time.Duration { func getJitter(v time.Duration) time.Duration {
if v == infinity { if v == infinity {
return 0 return 0

View File

@ -20,7 +20,6 @@ package transport
import ( import (
"bufio" "bufio"
"bytes"
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"io" "io"
@ -45,7 +44,7 @@ import (
const ( const (
// http2MaxFrameLen specifies the max length of a HTTP2 frame. // http2MaxFrameLen specifies the max length of a HTTP2 frame.
http2MaxFrameLen = 16384 // 16KB frame http2MaxFrameLen = 16384 // 16KB frame
// http://http2.github.io/http2-spec/#SettingValues // https://httpwg.org/specs/rfc7540.html#SettingValues
http2InitHeaderTableSize = 4096 http2InitHeaderTableSize = 4096
) )
@ -251,13 +250,13 @@ func encodeGrpcMessage(msg string) string {
} }
func encodeGrpcMessageUnchecked(msg string) string { func encodeGrpcMessageUnchecked(msg string) string {
var buf bytes.Buffer var sb strings.Builder
for len(msg) > 0 { for len(msg) > 0 {
r, size := utf8.DecodeRuneInString(msg) r, size := utf8.DecodeRuneInString(msg)
for _, b := range []byte(string(r)) { for _, b := range []byte(string(r)) {
if size > 1 { if size > 1 {
// If size > 1, r is not ascii. Always do percent encoding. // If size > 1, r is not ascii. Always do percent encoding.
buf.WriteString(fmt.Sprintf("%%%02X", b)) fmt.Fprintf(&sb, "%%%02X", b)
continue continue
} }
@ -266,14 +265,14 @@ func encodeGrpcMessageUnchecked(msg string) string {
// //
// fmt.Sprintf("%%%02X", utf8.RuneError) gives "%FFFD". // fmt.Sprintf("%%%02X", utf8.RuneError) gives "%FFFD".
if b >= spaceByte && b <= tildeByte && b != percentByte { if b >= spaceByte && b <= tildeByte && b != percentByte {
buf.WriteByte(b) sb.WriteByte(b)
} else { } else {
buf.WriteString(fmt.Sprintf("%%%02X", b)) fmt.Fprintf(&sb, "%%%02X", b)
} }
} }
msg = msg[size:] msg = msg[size:]
} }
return buf.String() return sb.String()
} }
// decodeGrpcMessage decodes the msg encoded by encodeGrpcMessage. // decodeGrpcMessage decodes the msg encoded by encodeGrpcMessage.
@ -291,23 +290,23 @@ func decodeGrpcMessage(msg string) string {
} }
func decodeGrpcMessageUnchecked(msg string) string { func decodeGrpcMessageUnchecked(msg string) string {
var buf bytes.Buffer var sb strings.Builder
lenMsg := len(msg) lenMsg := len(msg)
for i := 0; i < lenMsg; i++ { for i := 0; i < lenMsg; i++ {
c := msg[i] c := msg[i]
if c == percentByte && i+2 < lenMsg { if c == percentByte && i+2 < lenMsg {
parsed, err := strconv.ParseUint(msg[i+1:i+3], 16, 8) parsed, err := strconv.ParseUint(msg[i+1:i+3], 16, 8)
if err != nil { if err != nil {
buf.WriteByte(c) sb.WriteByte(c)
} else { } else {
buf.WriteByte(byte(parsed)) sb.WriteByte(byte(parsed))
i += 2 i += 2
} }
} else { } else {
buf.WriteByte(c) sb.WriteByte(c)
} }
} }
return buf.String() return sb.String()
} }
type bufWriter struct { type bufWriter struct {

View File

@ -50,7 +50,7 @@ type MD map[string][]string
// Keys beginning with "grpc-" are reserved for grpc-internal use only and may // Keys beginning with "grpc-" are reserved for grpc-internal use only and may
// result in errors if set in metadata. // result in errors if set in metadata.
func New(m map[string]string) MD { func New(m map[string]string) MD {
md := MD{} md := make(MD, len(m))
for k, val := range m { for k, val := range m {
key := strings.ToLower(k) key := strings.ToLower(k)
md[key] = append(md[key], val) md[key] = append(md[key], val)
@ -74,7 +74,7 @@ func Pairs(kv ...string) MD {
if len(kv)%2 == 1 { if len(kv)%2 == 1 {
panic(fmt.Sprintf("metadata: Pairs got the odd number of input pairs for metadata: %d", len(kv))) panic(fmt.Sprintf("metadata: Pairs got the odd number of input pairs for metadata: %d", len(kv)))
} }
md := MD{} md := make(MD, len(kv)/2)
for i := 0; i < len(kv); i += 2 { for i := 0; i < len(kv); i += 2 {
key := strings.ToLower(kv[i]) key := strings.ToLower(kv[i])
md[key] = append(md[key], kv[i+1]) md[key] = append(md[key], kv[i+1])
@ -182,19 +182,51 @@ func FromIncomingContext(ctx context.Context) (MD, bool) {
if !ok { if !ok {
return nil, false return nil, false
} }
out := MD{} out := make(MD, len(md))
for k, v := range md { for k, v := range md {
// We need to manually convert all keys to lower case, because MD is a // We need to manually convert all keys to lower case, because MD is a
// map, and there's no guarantee that the MD attached to the context is // map, and there's no guarantee that the MD attached to the context is
// created using our helper functions. // created using our helper functions.
key := strings.ToLower(k) key := strings.ToLower(k)
s := make([]string, len(v)) out[key] = copyOf(v)
copy(s, v)
out[key] = s
} }
return out, true return out, true
} }
// ValueFromIncomingContext returns the metadata value corresponding to the metadata
// key from the incoming metadata if it exists. Key must be lower-case.
//
// Experimental
//
// Notice: This API is EXPERIMENTAL and may be changed or removed in a
// later release.
func ValueFromIncomingContext(ctx context.Context, key string) []string {
md, ok := ctx.Value(mdIncomingKey{}).(MD)
if !ok {
return nil
}
if v, ok := md[key]; ok {
return copyOf(v)
}
for k, v := range md {
// We need to manually convert all keys to lower case, because MD is a
// map, and there's no guarantee that the MD attached to the context is
// created using our helper functions.
if strings.ToLower(k) == key {
return copyOf(v)
}
}
return nil
}
// the returned slice must not be modified in place
func copyOf(v []string) []string {
vals := make([]string, len(v))
copy(vals, v)
return vals
}
// FromOutgoingContextRaw returns the un-merged, intermediary contents of rawMD. // FromOutgoingContextRaw returns the un-merged, intermediary contents of rawMD.
// //
// Remember to perform strings.ToLower on the keys, for both the returned MD (MD // Remember to perform strings.ToLower on the keys, for both the returned MD (MD
@ -222,15 +254,18 @@ func FromOutgoingContext(ctx context.Context) (MD, bool) {
return nil, false return nil, false
} }
out := MD{} mdSize := len(raw.md)
for i := range raw.added {
mdSize += len(raw.added[i]) / 2
}
out := make(MD, mdSize)
for k, v := range raw.md { for k, v := range raw.md {
// We need to manually convert all keys to lower case, because MD is a // We need to manually convert all keys to lower case, because MD is a
// map, and there's no guarantee that the MD attached to the context is // map, and there's no guarantee that the MD attached to the context is
// created using our helper functions. // created using our helper functions.
key := strings.ToLower(k) key := strings.ToLower(k)
s := make([]string, len(v)) out[key] = copyOf(v)
copy(s, v)
out[key] = s
} }
for _, added := range raw.added { for _, added := range raw.added {
if len(added)%2 == 1 { if len(added)%2 == 1 {

View File

@ -1,3 +1,19 @@
// Copyright 2016 gRPC authors.
//
// 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.
// Service exported by server reflection
// Code generated by protoc-gen-go-grpc. DO NOT EDIT. // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions: // versions:
// - protoc-gen-go-grpc v1.2.0 // - protoc-gen-go-grpc v1.2.0

View File

@ -73,12 +73,14 @@ func init() {
internal.DrainServerTransports = func(srv *Server, addr string) { internal.DrainServerTransports = func(srv *Server, addr string) {
srv.drainServerTransports(addr) srv.drainServerTransports(addr)
} }
internal.AddExtraServerOptions = func(opt ...ServerOption) { internal.AddGlobalServerOptions = func(opt ...ServerOption) {
extraServerOptions = opt extraServerOptions = append(extraServerOptions, opt...)
} }
internal.ClearExtraServerOptions = func() { internal.ClearGlobalServerOptions = func() {
extraServerOptions = nil extraServerOptions = nil
} }
internal.BinaryLogger = binaryLogger
internal.JoinServerOptions = newJoinServerOption
} }
var statusOK = status.New(codes.OK, "") var statusOK = status.New(codes.OK, "")
@ -155,6 +157,7 @@ type serverOptions struct {
streamInt StreamServerInterceptor streamInt StreamServerInterceptor
chainUnaryInts []UnaryServerInterceptor chainUnaryInts []UnaryServerInterceptor
chainStreamInts []StreamServerInterceptor chainStreamInts []StreamServerInterceptor
binaryLogger binarylog.Logger
inTapHandle tap.ServerInHandle inTapHandle tap.ServerInHandle
statsHandlers []stats.Handler statsHandlers []stats.Handler
maxConcurrentStreams uint32 maxConcurrentStreams uint32
@ -214,6 +217,22 @@ func newFuncServerOption(f func(*serverOptions)) *funcServerOption {
} }
} }
// joinServerOption provides a way to combine arbitrary number of server
// options into one.
type joinServerOption struct {
opts []ServerOption
}
func (mdo *joinServerOption) apply(do *serverOptions) {
for _, opt := range mdo.opts {
opt.apply(do)
}
}
func newJoinServerOption(opts ...ServerOption) ServerOption {
return &joinServerOption{opts: opts}
}
// WriteBufferSize determines how much data can be batched before doing a write on the wire. // WriteBufferSize determines how much data can be batched before doing a write on the wire.
// The corresponding memory allocation for this buffer will be twice the size to keep syscalls low. // The corresponding memory allocation for this buffer will be twice the size to keep syscalls low.
// The default value for this buffer is 32KB. // The default value for this buffer is 32KB.
@ -452,6 +471,14 @@ func StatsHandler(h stats.Handler) ServerOption {
}) })
} }
// binaryLogger returns a ServerOption that can set the binary logger for the
// server.
func binaryLogger(bl binarylog.Logger) ServerOption {
return newFuncServerOption(func(o *serverOptions) {
o.binaryLogger = bl
})
}
// UnknownServiceHandler returns a ServerOption that allows for adding a custom // UnknownServiceHandler returns a ServerOption that allows for adding a custom
// unknown service handler. The provided method is a bidi-streaming RPC service // unknown service handler. The provided method is a bidi-streaming RPC service
// handler that will be invoked instead of returning the "unimplemented" gRPC // handler that will be invoked instead of returning the "unimplemented" gRPC
@ -1199,9 +1226,16 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.
} }
}() }()
} }
var binlogs []binarylog.MethodLogger
binlog := binarylog.GetMethodLogger(stream.Method()) if ml := binarylog.GetMethodLogger(stream.Method()); ml != nil {
if binlog != nil { binlogs = append(binlogs, ml)
}
if s.opts.binaryLogger != nil {
if ml := s.opts.binaryLogger.GetMethodLogger(stream.Method()); ml != nil {
binlogs = append(binlogs, ml)
}
}
if len(binlogs) != 0 {
ctx := stream.Context() ctx := stream.Context()
md, _ := metadata.FromIncomingContext(ctx) md, _ := metadata.FromIncomingContext(ctx)
logEntry := &binarylog.ClientHeader{ logEntry := &binarylog.ClientHeader{
@ -1221,7 +1255,9 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.
if peer, ok := peer.FromContext(ctx); ok { if peer, ok := peer.FromContext(ctx); ok {
logEntry.PeerAddr = peer.Addr logEntry.PeerAddr = peer.Addr
} }
binlog.Log(logEntry) for _, binlog := range binlogs {
binlog.Log(logEntry)
}
} }
// comp and cp are used for compression. decomp and dc are used for // comp and cp are used for compression. decomp and dc are used for
@ -1261,7 +1297,7 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.
} }
var payInfo *payloadInfo var payInfo *payloadInfo
if len(shs) != 0 || binlog != nil { if len(shs) != 0 || len(binlogs) != 0 {
payInfo = &payloadInfo{} payInfo = &payloadInfo{}
} }
d, err := recvAndDecompress(&parser{r: stream}, stream, dc, s.opts.maxReceiveMessageSize, payInfo, decomp) d, err := recvAndDecompress(&parser{r: stream}, stream, dc, s.opts.maxReceiveMessageSize, payInfo, decomp)
@ -1287,10 +1323,13 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.
Length: len(d), Length: len(d),
}) })
} }
if binlog != nil { if len(binlogs) != 0 {
binlog.Log(&binarylog.ClientMessage{ cm := &binarylog.ClientMessage{
Message: d, Message: d,
}) }
for _, binlog := range binlogs {
binlog.Log(cm)
}
} }
if trInfo != nil { if trInfo != nil {
trInfo.tr.LazyLog(&payload{sent: false, msg: v}, true) trInfo.tr.LazyLog(&payload{sent: false, msg: v}, true)
@ -1314,18 +1353,24 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.
if e := t.WriteStatus(stream, appStatus); e != nil { if e := t.WriteStatus(stream, appStatus); e != nil {
channelz.Warningf(logger, s.channelzID, "grpc: Server.processUnaryRPC failed to write status: %v", e) channelz.Warningf(logger, s.channelzID, "grpc: Server.processUnaryRPC failed to write status: %v", e)
} }
if binlog != nil { if len(binlogs) != 0 {
if h, _ := stream.Header(); h.Len() > 0 { if h, _ := stream.Header(); h.Len() > 0 {
// Only log serverHeader if there was header. Otherwise it can // Only log serverHeader if there was header. Otherwise it can
// be trailer only. // be trailer only.
binlog.Log(&binarylog.ServerHeader{ sh := &binarylog.ServerHeader{
Header: h, Header: h,
}) }
for _, binlog := range binlogs {
binlog.Log(sh)
}
} }
binlog.Log(&binarylog.ServerTrailer{ st := &binarylog.ServerTrailer{
Trailer: stream.Trailer(), Trailer: stream.Trailer(),
Err: appErr, Err: appErr,
}) }
for _, binlog := range binlogs {
binlog.Log(st)
}
} }
return appErr return appErr
} }
@ -1351,26 +1396,34 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.
panic(fmt.Sprintf("grpc: Unexpected error (%T) from sendResponse: %v", st, st)) panic(fmt.Sprintf("grpc: Unexpected error (%T) from sendResponse: %v", st, st))
} }
} }
if binlog != nil { if len(binlogs) != 0 {
h, _ := stream.Header() h, _ := stream.Header()
binlog.Log(&binarylog.ServerHeader{ sh := &binarylog.ServerHeader{
Header: h, Header: h,
}) }
binlog.Log(&binarylog.ServerTrailer{ st := &binarylog.ServerTrailer{
Trailer: stream.Trailer(), Trailer: stream.Trailer(),
Err: appErr, Err: appErr,
}) }
for _, binlog := range binlogs {
binlog.Log(sh)
binlog.Log(st)
}
} }
return err return err
} }
if binlog != nil { if len(binlogs) != 0 {
h, _ := stream.Header() h, _ := stream.Header()
binlog.Log(&binarylog.ServerHeader{ sh := &binarylog.ServerHeader{
Header: h, Header: h,
}) }
binlog.Log(&binarylog.ServerMessage{ sm := &binarylog.ServerMessage{
Message: reply, Message: reply,
}) }
for _, binlog := range binlogs {
binlog.Log(sh)
binlog.Log(sm)
}
} }
if channelz.IsOn() { if channelz.IsOn() {
t.IncrMsgSent() t.IncrMsgSent()
@ -1382,11 +1435,14 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.
// Should the logging be in WriteStatus? Should we ignore the WriteStatus // Should the logging be in WriteStatus? Should we ignore the WriteStatus
// error or allow the stats handler to see it? // error or allow the stats handler to see it?
err = t.WriteStatus(stream, statusOK) err = t.WriteStatus(stream, statusOK)
if binlog != nil { if len(binlogs) != 0 {
binlog.Log(&binarylog.ServerTrailer{ st := &binarylog.ServerTrailer{
Trailer: stream.Trailer(), Trailer: stream.Trailer(),
Err: appErr, Err: appErr,
}) }
for _, binlog := range binlogs {
binlog.Log(st)
}
} }
return err return err
} }
@ -1499,8 +1555,15 @@ func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transp
}() }()
} }
ss.binlog = binarylog.GetMethodLogger(stream.Method()) if ml := binarylog.GetMethodLogger(stream.Method()); ml != nil {
if ss.binlog != nil { ss.binlogs = append(ss.binlogs, ml)
}
if s.opts.binaryLogger != nil {
if ml := s.opts.binaryLogger.GetMethodLogger(stream.Method()); ml != nil {
ss.binlogs = append(ss.binlogs, ml)
}
}
if len(ss.binlogs) != 0 {
md, _ := metadata.FromIncomingContext(ctx) md, _ := metadata.FromIncomingContext(ctx)
logEntry := &binarylog.ClientHeader{ logEntry := &binarylog.ClientHeader{
Header: md, Header: md,
@ -1519,7 +1582,9 @@ func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transp
if peer, ok := peer.FromContext(ss.Context()); ok { if peer, ok := peer.FromContext(ss.Context()); ok {
logEntry.PeerAddr = peer.Addr logEntry.PeerAddr = peer.Addr
} }
ss.binlog.Log(logEntry) for _, binlog := range ss.binlogs {
binlog.Log(logEntry)
}
} }
// If dc is set and matches the stream's compression, use it. Otherwise, try // If dc is set and matches the stream's compression, use it. Otherwise, try
@ -1585,11 +1650,14 @@ func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transp
ss.mu.Unlock() ss.mu.Unlock()
} }
t.WriteStatus(ss.s, appStatus) t.WriteStatus(ss.s, appStatus)
if ss.binlog != nil { if len(ss.binlogs) != 0 {
ss.binlog.Log(&binarylog.ServerTrailer{ st := &binarylog.ServerTrailer{
Trailer: ss.s.Trailer(), Trailer: ss.s.Trailer(),
Err: appErr, Err: appErr,
}) }
for _, binlog := range ss.binlogs {
binlog.Log(st)
}
} }
// TODO: Should we log an error from WriteStatus here and below? // TODO: Should we log an error from WriteStatus here and below?
return appErr return appErr
@ -1600,11 +1668,14 @@ func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transp
ss.mu.Unlock() ss.mu.Unlock()
} }
err = t.WriteStatus(ss.s, statusOK) err = t.WriteStatus(ss.s, statusOK)
if ss.binlog != nil { if len(ss.binlogs) != 0 {
ss.binlog.Log(&binarylog.ServerTrailer{ st := &binarylog.ServerTrailer{
Trailer: ss.s.Trailer(), Trailer: ss.s.Trailer(),
Err: appErr, Err: appErr,
}) }
for _, binlog := range ss.binlogs {
binlog.Log(st)
}
} }
return err return err
} }

View File

@ -301,7 +301,14 @@ func newClientStreamWithParams(ctx context.Context, desc *StreamDesc, cc *Client
if !cc.dopts.disableRetry { if !cc.dopts.disableRetry {
cs.retryThrottler = cc.retryThrottler.Load().(*retryThrottler) cs.retryThrottler = cc.retryThrottler.Load().(*retryThrottler)
} }
cs.binlog = binarylog.GetMethodLogger(method) if ml := binarylog.GetMethodLogger(method); ml != nil {
cs.binlogs = append(cs.binlogs, ml)
}
if cc.dopts.binaryLogger != nil {
if ml := cc.dopts.binaryLogger.GetMethodLogger(method); ml != nil {
cs.binlogs = append(cs.binlogs, ml)
}
}
// Pick the transport to use and create a new stream on the transport. // Pick the transport to use and create a new stream on the transport.
// Assign cs.attempt upon success. // Assign cs.attempt upon success.
@ -322,7 +329,7 @@ func newClientStreamWithParams(ctx context.Context, desc *StreamDesc, cc *Client
return nil, err return nil, err
} }
if cs.binlog != nil { if len(cs.binlogs) != 0 {
md, _ := metadata.FromOutgoingContext(ctx) md, _ := metadata.FromOutgoingContext(ctx)
logEntry := &binarylog.ClientHeader{ logEntry := &binarylog.ClientHeader{
OnClientSide: true, OnClientSide: true,
@ -336,7 +343,9 @@ func newClientStreamWithParams(ctx context.Context, desc *StreamDesc, cc *Client
logEntry.Timeout = 0 logEntry.Timeout = 0
} }
} }
cs.binlog.Log(logEntry) for _, binlog := range cs.binlogs {
binlog.Log(logEntry)
}
} }
if desc != unaryStreamDesc { if desc != unaryStreamDesc {
@ -480,7 +489,7 @@ type clientStream struct {
retryThrottler *retryThrottler // The throttler active when the RPC began. retryThrottler *retryThrottler // The throttler active when the RPC began.
binlog binarylog.MethodLogger // Binary logger, can be nil. binlogs []binarylog.MethodLogger
// serverHeaderBinlogged is a boolean for whether server header has been // serverHeaderBinlogged is a boolean for whether server header has been
// logged. Server header will be logged when the first time one of those // logged. Server header will be logged when the first time one of those
// happens: stream.Header(), stream.Recv(). // happens: stream.Header(), stream.Recv().
@ -744,7 +753,7 @@ func (cs *clientStream) Header() (metadata.MD, error) {
cs.finish(err) cs.finish(err)
return nil, err return nil, err
} }
if cs.binlog != nil && !cs.serverHeaderBinlogged { if len(cs.binlogs) != 0 && !cs.serverHeaderBinlogged {
// Only log if binary log is on and header has not been logged. // Only log if binary log is on and header has not been logged.
logEntry := &binarylog.ServerHeader{ logEntry := &binarylog.ServerHeader{
OnClientSide: true, OnClientSide: true,
@ -754,8 +763,10 @@ func (cs *clientStream) Header() (metadata.MD, error) {
if peer, ok := peer.FromContext(cs.Context()); ok { if peer, ok := peer.FromContext(cs.Context()); ok {
logEntry.PeerAddr = peer.Addr logEntry.PeerAddr = peer.Addr
} }
cs.binlog.Log(logEntry)
cs.serverHeaderBinlogged = true cs.serverHeaderBinlogged = true
for _, binlog := range cs.binlogs {
binlog.Log(logEntry)
}
} }
return m, nil return m, nil
} }
@ -829,38 +840,44 @@ func (cs *clientStream) SendMsg(m interface{}) (err error) {
return a.sendMsg(m, hdr, payload, data) return a.sendMsg(m, hdr, payload, data)
} }
err = cs.withRetry(op, func() { cs.bufferForRetryLocked(len(hdr)+len(payload), op) }) err = cs.withRetry(op, func() { cs.bufferForRetryLocked(len(hdr)+len(payload), op) })
if cs.binlog != nil && err == nil { if len(cs.binlogs) != 0 && err == nil {
cs.binlog.Log(&binarylog.ClientMessage{ cm := &binarylog.ClientMessage{
OnClientSide: true, OnClientSide: true,
Message: data, Message: data,
}) }
for _, binlog := range cs.binlogs {
binlog.Log(cm)
}
} }
return err return err
} }
func (cs *clientStream) RecvMsg(m interface{}) error { func (cs *clientStream) RecvMsg(m interface{}) error {
if cs.binlog != nil && !cs.serverHeaderBinlogged { if len(cs.binlogs) != 0 && !cs.serverHeaderBinlogged {
// Call Header() to binary log header if it's not already logged. // Call Header() to binary log header if it's not already logged.
cs.Header() cs.Header()
} }
var recvInfo *payloadInfo var recvInfo *payloadInfo
if cs.binlog != nil { if len(cs.binlogs) != 0 {
recvInfo = &payloadInfo{} recvInfo = &payloadInfo{}
} }
err := cs.withRetry(func(a *csAttempt) error { err := cs.withRetry(func(a *csAttempt) error {
return a.recvMsg(m, recvInfo) return a.recvMsg(m, recvInfo)
}, cs.commitAttemptLocked) }, cs.commitAttemptLocked)
if cs.binlog != nil && err == nil { if len(cs.binlogs) != 0 && err == nil {
cs.binlog.Log(&binarylog.ServerMessage{ sm := &binarylog.ServerMessage{
OnClientSide: true, OnClientSide: true,
Message: recvInfo.uncompressedBytes, Message: recvInfo.uncompressedBytes,
}) }
for _, binlog := range cs.binlogs {
binlog.Log(sm)
}
} }
if err != nil || !cs.desc.ServerStreams { if err != nil || !cs.desc.ServerStreams {
// err != nil or non-server-streaming indicates end of stream. // err != nil or non-server-streaming indicates end of stream.
cs.finish(err) cs.finish(err)
if cs.binlog != nil { if len(cs.binlogs) != 0 {
// finish will not log Trailer. Log Trailer here. // finish will not log Trailer. Log Trailer here.
logEntry := &binarylog.ServerTrailer{ logEntry := &binarylog.ServerTrailer{
OnClientSide: true, OnClientSide: true,
@ -873,7 +890,9 @@ func (cs *clientStream) RecvMsg(m interface{}) error {
if peer, ok := peer.FromContext(cs.Context()); ok { if peer, ok := peer.FromContext(cs.Context()); ok {
logEntry.PeerAddr = peer.Addr logEntry.PeerAddr = peer.Addr
} }
cs.binlog.Log(logEntry) for _, binlog := range cs.binlogs {
binlog.Log(logEntry)
}
} }
} }
return err return err
@ -894,10 +913,13 @@ func (cs *clientStream) CloseSend() error {
return nil return nil
} }
cs.withRetry(op, func() { cs.bufferForRetryLocked(0, op) }) cs.withRetry(op, func() { cs.bufferForRetryLocked(0, op) })
if cs.binlog != nil { if len(cs.binlogs) != 0 {
cs.binlog.Log(&binarylog.ClientHalfClose{ chc := &binarylog.ClientHalfClose{
OnClientSide: true, OnClientSide: true,
}) }
for _, binlog := range cs.binlogs {
binlog.Log(chc)
}
} }
// We never returned an error here for reasons. // We never returned an error here for reasons.
return nil return nil
@ -930,10 +952,13 @@ func (cs *clientStream) finish(err error) {
// //
// Only one of cancel or trailer needs to be logged. In the cases where // Only one of cancel or trailer needs to be logged. In the cases where
// users don't call RecvMsg, users must have already canceled the RPC. // users don't call RecvMsg, users must have already canceled the RPC.
if cs.binlog != nil && status.Code(err) == codes.Canceled { if len(cs.binlogs) != 0 && status.Code(err) == codes.Canceled {
cs.binlog.Log(&binarylog.Cancel{ c := &binarylog.Cancel{
OnClientSide: true, OnClientSide: true,
}) }
for _, binlog := range cs.binlogs {
binlog.Log(c)
}
} }
if err == nil { if err == nil {
cs.retryThrottler.successfulRPC() cs.retryThrottler.successfulRPC()
@ -1005,6 +1030,7 @@ func (a *csAttempt) recvMsg(m interface{}, payInfo *payloadInfo) (err error) {
} }
return io.EOF // indicates successful end of stream. return io.EOF // indicates successful end of stream.
} }
return toRPCErr(err) return toRPCErr(err)
} }
if a.trInfo != nil { if a.trInfo != nil {
@ -1453,7 +1479,7 @@ type serverStream struct {
statsHandler []stats.Handler statsHandler []stats.Handler
binlog binarylog.MethodLogger binlogs []binarylog.MethodLogger
// serverHeaderBinlogged indicates whether server header has been logged. It // serverHeaderBinlogged indicates whether server header has been logged. It
// will happen when one of the following two happens: stream.SendHeader(), // will happen when one of the following two happens: stream.SendHeader(),
// stream.Send(). // stream.Send().
@ -1487,12 +1513,15 @@ func (ss *serverStream) SendHeader(md metadata.MD) error {
} }
err = ss.t.WriteHeader(ss.s, md) err = ss.t.WriteHeader(ss.s, md)
if ss.binlog != nil && !ss.serverHeaderBinlogged { if len(ss.binlogs) != 0 && !ss.serverHeaderBinlogged {
h, _ := ss.s.Header() h, _ := ss.s.Header()
ss.binlog.Log(&binarylog.ServerHeader{ sh := &binarylog.ServerHeader{
Header: h, Header: h,
}) }
ss.serverHeaderBinlogged = true ss.serverHeaderBinlogged = true
for _, binlog := range ss.binlogs {
binlog.Log(sh)
}
} }
return err return err
} }
@ -1549,17 +1578,23 @@ func (ss *serverStream) SendMsg(m interface{}) (err error) {
if err := ss.t.Write(ss.s, hdr, payload, &transport.Options{Last: false}); err != nil { if err := ss.t.Write(ss.s, hdr, payload, &transport.Options{Last: false}); err != nil {
return toRPCErr(err) return toRPCErr(err)
} }
if ss.binlog != nil { if len(ss.binlogs) != 0 {
if !ss.serverHeaderBinlogged { if !ss.serverHeaderBinlogged {
h, _ := ss.s.Header() h, _ := ss.s.Header()
ss.binlog.Log(&binarylog.ServerHeader{ sh := &binarylog.ServerHeader{
Header: h, Header: h,
}) }
ss.serverHeaderBinlogged = true ss.serverHeaderBinlogged = true
for _, binlog := range ss.binlogs {
binlog.Log(sh)
}
} }
ss.binlog.Log(&binarylog.ServerMessage{ sm := &binarylog.ServerMessage{
Message: data, Message: data,
}) }
for _, binlog := range ss.binlogs {
binlog.Log(sm)
}
} }
if len(ss.statsHandler) != 0 { if len(ss.statsHandler) != 0 {
for _, sh := range ss.statsHandler { for _, sh := range ss.statsHandler {
@ -1598,13 +1633,16 @@ func (ss *serverStream) RecvMsg(m interface{}) (err error) {
} }
}() }()
var payInfo *payloadInfo var payInfo *payloadInfo
if len(ss.statsHandler) != 0 || ss.binlog != nil { if len(ss.statsHandler) != 0 || len(ss.binlogs) != 0 {
payInfo = &payloadInfo{} payInfo = &payloadInfo{}
} }
if err := recv(ss.p, ss.codec, ss.s, ss.dc, m, ss.maxReceiveMessageSize, payInfo, ss.decomp); err != nil { if err := recv(ss.p, ss.codec, ss.s, ss.dc, m, ss.maxReceiveMessageSize, payInfo, ss.decomp); err != nil {
if err == io.EOF { if err == io.EOF {
if ss.binlog != nil { if len(ss.binlogs) != 0 {
ss.binlog.Log(&binarylog.ClientHalfClose{}) chc := &binarylog.ClientHalfClose{}
for _, binlog := range ss.binlogs {
binlog.Log(chc)
}
} }
return err return err
} }
@ -1625,10 +1663,13 @@ func (ss *serverStream) RecvMsg(m interface{}) (err error) {
}) })
} }
} }
if ss.binlog != nil { if len(ss.binlogs) != 0 {
ss.binlog.Log(&binarylog.ClientMessage{ cm := &binarylog.ClientMessage{
Message: payInfo.uncompressedBytes, Message: payInfo.uncompressedBytes,
}) }
for _, binlog := range ss.binlogs {
binlog.Log(cm)
}
} }
return nil return nil
} }

View File

@ -19,4 +19,4 @@
package grpc package grpc
// Version is the current grpc version. // Version is the current grpc version.
const Version = "1.49.0" const Version = "1.50.1"

2
vendor/modules.txt vendored
View File

@ -698,7 +698,7 @@ google.golang.org/appengine/urlfetch
google.golang.org/genproto/googleapis/api/httpbody google.golang.org/genproto/googleapis/api/httpbody
google.golang.org/genproto/googleapis/rpc/status google.golang.org/genproto/googleapis/rpc/status
google.golang.org/genproto/protobuf/field_mask google.golang.org/genproto/protobuf/field_mask
# google.golang.org/grpc v1.49.0 # google.golang.org/grpc v1.50.1
## explicit; go 1.17 ## explicit; go 1.17
google.golang.org/grpc google.golang.org/grpc
google.golang.org/grpc/attributes google.golang.org/grpc/attributes