Package visigrpc
provide some functions to help you making a gRPC server. Errors logged on Sentry, Panic interceptor, HTTP status to gRPC code, ... Everything is made to assist you :)
Use go get
to install this package.
go get github.com/visiperf/visigrpc
The Error(code codes.Code, msg string) error
function is used to return a gRPC error and log it into Sentry.
type server struct { }
func main() {
// init Sentry config
if err := sentry.Init(sentry.ClientOptions{
Dsn: SENTRY_DSN,
Environment: SENTRY_ENV,
Transport: sentry.NewHTTPSyncTransport(),
}); err != nil {
...
}
// gRPC server
lis, err := net.Listen("tcp", ":9090")
if err != nil {
...
}
s := grpc.NewServer()
RegisterServiceServer(s, &server{})
if err := s.Serve(lis); err != nil {
...
}
}
func (s *server) Get(ctx context.Context, in *GetRequest) (*GetResponse, error) {
return nil, status.Error(codes.Unimplemented, "implement me")
}
The New(code codes.Code, msg string) *spb.Status
function has same process as Error(...) error
function, but returns a *spb.Status
instance instead of error
.
type server struct { }
func main() {
// init Sentry config
if err := sentry.Init(sentry.ClientOptions{
Dsn: SENTRY_DSN,
Environment: SENTRY_ENV,
Transport: sentry.NewHTTPSyncTransport(),
}); err != nil {
...
}
// gRPC server
lis, err := net.Listen("tcp", ":9090")
if err != nil {
...
}
s := grpc.NewServer()
RegisterServiceServer(s, &server{})
if err := s.Serve(lis); err != nil {
...
}
}
func (s *server) Get(ctx context.Context, in *GetRequest) (*GetResponse, error) {
st := status.New(codes.Internal, "Oups, an error !")
// st.Code -> codes.Internal
// st.Message -> "Oups, an error !"
...
return nil, status.Error(codes.Unimplemented, "implement me")
}
If you receive a gRPC error (made with status.Error(...)), you can decode it with FromError(err error) *spb.Status
to retrieve the gRPC code and message.
type server struct { }
func main() {
// init Sentry config
if err := sentry.Init(sentry.ClientOptions{
Dsn: SENTRY_DSN,
Environment: SENTRY_ENV,
Transport: sentry.NewHTTPSyncTransport(),
}); err != nil {
...
}
// gRPC server
lis, err := net.Listen("tcp", ":9090")
if err != nil {
...
}
s := grpc.NewServer()
RegisterServiceServer(s, &server{})
if err := s.Serve(lis); err != nil {
...
}
}
func (s *server) Get(ctx context.Context, in *GetRequest) (*GetResponse, error) {
return nil, status.Error(codes.Unimplemented, "implement me")
}
func (s *server) Create(ctx context.Context, in *CreateRequest) (*CreateResponse, error) {
resp, err := s.Get(ctx, &GetRequest{}) // just for example, never directly call self functions with `s *server` !
if err != nil {
st := status.FromError(err)
// st.Code -> codes.Unimplemented
// st.Message -> "implement me"
...
}
return nil, status.Error(codes.Unimplemented, "implement me")
}
If you make an HTTP request, you can use the GrpcCodeFromHttpStatus(status int) codes.Code
func to convert HTTP status code in response to gRPC code.
code := status.GrpcCodeFromHttpStatus(http.StatusForbidden) // http status -> 403 (Forbidden)
// code -> 7 (codes.PermissionDenied)
Visigrpc also provide a RecoveryHandler
to capture and log panics for Unary
and Stream
functions.
type server struct { }
func main() {
// init Sentry config
if err := sentry.Init(sentry.ClientOptions{
Dsn: SENTRY_DSN,
Environment: SENTRY_ENV,
Transport: sentry.NewHTTPSyncTransport(),
}); err != nil {
...
}
// gRPC server
lis, err := net.Listen("tcp", ":9090")
if err != nil {
...
}
var opts = []grpc_recovery.Option{
grpc_recovery.WithRecoveryHandler(visigrpc.RecoveryHandler),
}
s := grpc.NewServer(
grpc_middleware.WithUnaryServerChain(
grpc_recovery.UnaryServerInterceptor(opts...),
),
grpc_middleware.WithStreamServerChain(
grpc_recovery.StreamServerInterceptor(opts...),
),
)
RegisterServiceServer(s, &server{})
if err := s.Serve(lis); err != nil {
...
}
}
func (s *server) Get(ctx context.Context, in *GetRequest) (*GetResponse, error) {
panic("implement me") // will return codes.Unknown with message "implement me" and log error on Sentry
}
- Sentry : github.com/getsentry/sentry-go
- Go gRPC Middleware : github.com/grpc-ecosystem/go-grpc-middleware