Add Inner Ring code

This commit is contained in:
Stanislav Bogatyrev 2020-07-24 16:54:03 +03:00
parent dadfd90dcd
commit b7b5079934
400 changed files with 11420 additions and 8690 deletions

View file

@ -0,0 +1,141 @@
package grpc
import (
"context"
"github.com/gogo/protobuf/proto"
"github.com/nspcc-dev/neofs-api-go/refs"
"github.com/prometheus/client_golang/prometheus"
"google.golang.org/grpc"
)
type (
billingStream struct {
grpc.ServerStream
*grpc.StreamServerInfo
input int
output int
cid string
}
cider interface {
CID() refs.CID
}
)
const (
typeInput = "input"
typeOutput = "output"
labelType = "type"
labelMethod = "method"
labelContainer = "container"
)
var (
serviceBillingBytes = prometheus.NewCounterVec(prometheus.CounterOpts{
Namespace: "neofs",
Name: "billing_bytes",
Help: "Count of bytes received / sent for method and container",
}, []string{labelType, labelMethod, labelContainer})
serviceBillingCalls = prometheus.NewCounterVec(prometheus.CounterOpts{
Namespace: "neofs",
Name: "billing_calls",
Help: "Count of calls for api methods",
}, []string{labelMethod, labelContainer})
)
func init() {
// Register billing metrics
prometheus.MustRegister(serviceBillingBytes)
prometheus.MustRegister(serviceBillingCalls)
}
func getProtoSize(val interface{}) int {
if msg, ok := val.(proto.Message); ok && msg != nil {
return proto.Size(msg)
}
return 0
}
func getProtoContainer(val interface{}) string {
if t, ok := val.(cider); ok && t != nil {
return t.CID().String()
}
return ""
}
func (b *billingStream) RecvMsg(msg interface{}) error {
err := b.ServerStream.RecvMsg(msg)
b.input += getProtoSize(msg)
if cid := getProtoContainer(msg); cid != "" {
b.cid = cid
}
return err
}
func (b *billingStream) SendMsg(msg interface{}) error {
b.output += getProtoSize(msg)
return b.ServerStream.SendMsg(msg)
}
func (b *billingStream) report() {
labels := prometheus.Labels{
labelMethod: b.FullMethod,
labelContainer: b.cid,
}
serviceBillingCalls.With(labels).Inc()
labels[labelType] = typeInput
serviceBillingBytes.With(labels).Add(float64(b.input))
labels[labelType] = typeOutput
serviceBillingBytes.With(labels).Add(float64(b.output))
}
func streamBilling(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
stream := &billingStream{
ServerStream: ss,
StreamServerInfo: info,
}
err := handler(srv, stream)
stream.report()
return err
}
func unaryBilling(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (res interface{}, err error) {
input := getProtoSize(req)
cid := getProtoContainer(req)
labels := prometheus.Labels{
labelMethod: info.FullMethod,
labelContainer: cid,
}
serviceBillingCalls.With(labels).Inc()
if res, err = handler(ctx, req); err != nil {
return
}
output := getProtoSize(res)
labels[labelType] = typeInput
serviceBillingBytes.With(labels).Add(float64(input))
labels[labelType] = typeOutput
serviceBillingBytes.With(labels).Add(float64(output))
return
}

View file

@ -0,0 +1,8 @@
package grpc
import "github.com/nspcc-dev/neofs-node/cmd/neofs-node/modules/fix/module"
// Module is a gRPC layer module.
var Module = module.Module{
{Constructor: routing},
}

View file

@ -0,0 +1,115 @@
// About "github.com/nspcc-dev/neofs-node/lib/grpc"
// there's just alias for "google.golang.org/grpc"
// with Service-interface
package grpc
import (
middleware "github.com/grpc-ecosystem/go-grpc-middleware"
gZap "github.com/grpc-ecosystem/go-grpc-middleware/logging/zap"
prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
libgrpc "github.com/nspcc-dev/neofs-node/pkg/network/transport/grpc"
"github.com/spf13/viper"
"go.uber.org/dig"
"go.uber.org/zap"
"google.golang.org/grpc"
)
type (
Service = libgrpc.Service
// ServerParams to create gRPC-server
// and provide service-handlers
ServerParams struct {
dig.In
Services []Service
Logger *zap.Logger
Viper *viper.Viper
}
// ServicesResult ...
ServicesResult struct {
dig.Out
Services []Service
}
// Server type-alias
Server = grpc.Server
// CallOption type-alias
CallOption = grpc.CallOption
// ClientConn type-alias
ClientConn = grpc.ClientConn
// ServerOption type-alias
ServerOption = grpc.ServerOption
)
var (
// DialContext func-alias
DialContext = grpc.DialContext
// WithBlock func-alias
WithBlock = grpc.WithBlock
// WithInsecure func-alias
WithInsecure = grpc.WithInsecure
)
// NewServer creates a gRPC server which has no service registered and has not
// started to accept requests yet.
func NewServer(opts ...ServerOption) *Server {
return grpc.NewServer(opts...)
}
// creates new gRPC server and attach handlers.
func routing(p ServerParams) *grpc.Server {
var (
options []ServerOption
stream []grpc.StreamServerInterceptor
unary []grpc.UnaryServerInterceptor
)
if p.Viper.GetBool("node.grpc.billing") {
unary = append(unary, unaryBilling)
stream = append(stream, streamBilling)
}
if p.Viper.GetBool("node.grpc.logging") {
stream = append(stream, gZap.StreamServerInterceptor(p.Logger))
unary = append(unary, gZap.UnaryServerInterceptor(p.Logger))
}
if p.Viper.GetBool("node.grpc.metrics") {
stream = append(stream, prometheus.StreamServerInterceptor)
unary = append(unary, prometheus.UnaryServerInterceptor)
}
// Add stream options:
if len(stream) > 0 {
options = append(options,
grpc.StreamInterceptor(middleware.ChainStreamServer(stream...)),
)
}
// Add unary options:
if len(unary) > 0 {
options = append(options,
grpc.UnaryInterceptor(middleware.ChainUnaryServer(unary...)),
)
}
g := grpc.NewServer(options...)
// Service services here:
for _, service := range p.Services {
p.Logger.Info("register gRPC service",
zap.String("service", service.Name()))
service.Register(g)
}
return g
}