2021-10-11 13:00:58 -03:00

109 lines
4.2 KiB
Go

// Copyright (c) 2021 Gitpod GmbH. All rights reserved.
// Licensed under the GNU Affero General Public License (AGPL).
// See License-AGPL.txt in the project root for license information.
package grpc
import (
"time"
"github.com/gitpod-io/gitpod/common-go/log"
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
grpc_opentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
"github.com/opentracing/opentracing-go"
"github.com/prometheus/client_golang/prometheus"
"github.com/sirupsen/logrus"
"google.golang.org/grpc"
"google.golang.org/grpc/backoff"
"google.golang.org/grpc/grpclog"
"google.golang.org/grpc/keepalive"
)
// maxMsgSize use 16MB as the default message size limit.
// grpc library default is 4MB
const maxMsgSize = 1024 * 1024 * 16
var defaultClientOptionsConfig struct {
Metrics *grpc_prometheus.ClientMetrics
}
// ClientMetrics produces client-side gRPC metrics
func ClientMetrics() prometheus.Collector {
res := grpc_prometheus.NewClientMetrics()
defaultClientOptionsConfig.Metrics = res
return res
}
// DefaultClientOptions returns the default grpc client connection options
func DefaultClientOptions() []grpc.DialOption {
bfConf := backoff.DefaultConfig
bfConf.MaxDelay = 5 * time.Second
var (
unaryInterceptor = []grpc.UnaryClientInterceptor{
grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(opentracing.GlobalTracer())),
}
streamInterceptor = []grpc.StreamClientInterceptor{
grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(opentracing.GlobalTracer())),
}
)
if defaultClientOptionsConfig.Metrics != nil {
unaryInterceptor = append(unaryInterceptor, defaultClientOptionsConfig.Metrics.UnaryClientInterceptor())
streamInterceptor = append(streamInterceptor, defaultClientOptionsConfig.Metrics.StreamClientInterceptor())
}
res := []grpc.DialOption{
grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(unaryInterceptor...)),
grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(streamInterceptor...)),
grpc.WithBlock(),
grpc.WithConnectParams(grpc.ConnectParams{
Backoff: bfConf,
}),
grpc.WithKeepaliveParams(keepalive.ClientParameters{
Time: 10 * time.Second,
Timeout: time.Second,
PermitWithoutStream: true,
}),
grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(maxMsgSize)),
}
return res
}
// DefaultServerOptions returns the default ServerOption sets options for internal components
func DefaultServerOptions() []grpc.ServerOption {
return ServerOptionsWithInterceptors([]grpc.StreamServerInterceptor{}, []grpc.UnaryServerInterceptor{})
}
// ServerOptionsWithInterceptors returns the default ServerOption sets options for internal components with additional interceptors.
// By default, Interceptors for OpenTracing (grpc_opentracing) are added as the last one.
func ServerOptionsWithInterceptors(stream []grpc.StreamServerInterceptor, unary []grpc.UnaryServerInterceptor) []grpc.ServerOption {
stream = append(stream, grpc_opentracing.StreamServerInterceptor(grpc_opentracing.WithTracer(opentracing.GlobalTracer())))
unary = append(unary, grpc_opentracing.UnaryServerInterceptor(grpc_opentracing.WithTracer(opentracing.GlobalTracer())))
return []grpc.ServerOption{
// terminate the connection if the client pings more than once every 2 seconds
grpc.KeepaliveEnforcementPolicy(keepalive.EnforcementPolicy{
MinTime: 10 * time.Second,
PermitWithoutStream: true,
}),
grpc.MaxRecvMsgSize(maxMsgSize),
// We don't know how good our cients are at closing connections. If they don't close them properly
// we'll be leaking goroutines left and right. Closing Idle connections should prevent that.
grpc.KeepaliveParams(keepalive.ServerParameters{
MaxConnectionIdle: 30 * time.Minute,
}),
grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(stream...)),
grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(unary...)),
}
}
func SetupLogging() {
grpclog.SetLoggerV2(grpclog.NewLoggerV2(
log.WithField("component", "grpc").WriterLevel(logrus.DebugLevel),
log.WithField("component", "grpc").WriterLevel(logrus.WarnLevel),
log.WithField("component", "grpc").WriterLevel(logrus.ErrorLevel),
))
}