gRPC server module based on gRPC-Go.
go get github.com/ankorstore/yokai/grpcserver
This module provides a GrpcServerFactory, allowing to build an grpc.Server
instance.
package main
import (
"github.com/ankorstore/yokai/grpcserver"
"google.golang.org/grpc"
)
var server, _ = grpcserver.NewDefaultGrpcServerFactory().Create()
// equivalent to:
var server, _ = grpcserver.NewDefaultGrpcServerFactory().Create(
grpcserver.WithServerOptions([]grpc.ServerOption{}), // no specific server options by default
grpcserver.WithReflection(false), // reflection disabled by default
)
See gRPC-Go documentation for more details.
This module provides several add-ons ready to use to enrich your gRPC server.
This module provides the possibility to easily enable gRPC server reflection, disabled by default:
package main
import (
"github.com/ankorstore/yokai/grpcserver"
)
func main() {
server, _ := grpcserver.NewDefaultGrpcServerFactory().Create(
grpcserver.WithReflection(true),
)
}
Reflection usage is helpful for developing or testing your gRPC services, but it is not recommended for production usage.
This module provides an GrpcPanicRecoveryHandler, compatible with the recovery interceptor, to automatically recover from panics in your gRPC services:
package main
import (
"github.com/ankorstore/yokai/grpcserver"
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/recovery"
"google.golang.org/grpc"
)
func main() {
handler := grpcserver.NewGrpcPanicRecoveryHandler()
server, _ := grpcserver.NewDefaultGrpcServerFactory().Create(
grpcserver.WithServerOptions(
grpc.UnaryInterceptor(recovery.UnaryServerInterceptor(recovery.WithRecoveryHandlerContext(handler.Handle(false)))),
grpc.StreamInterceptor(recovery.StreamServerInterceptor(recovery.WithRecoveryHandlerContext(handler.Handle(false)))),
),
)
}
You can also use Handle(true)
to append on the handler gRPC response and logs more information about the panic and the debug stack (
not suitable for production).
This module provides a GrpcLoggerInterceptor to automatically log unary and streaming RPCs calls (status, type, duration, etc.), compatible with the log module.
Using this interceptor will also provide a logger instance in the context, that you can retrieve with the CtxLogger method to produce correlated logs from your gRPC services.
package main
import (
"github.com/ankorstore/yokai/generate/uuid"
"github.com/ankorstore/yokai/grpcserver"
"github.com/ankorstore/yokai/log"
"google.golang.org/grpc"
)
func main() {
logger, _ := log.NewDefaultLoggerFactory().Create()
loggerInterceptor := grpcserver.NewGrpcLoggerInterceptor(uuid.NewDefaultUuidGenerator, logger)
server, _ := grpcserver.NewDefaultGrpcServerFactory().Create(
grpcserver.WithServerOptions(
grpc.UnaryInterceptor(loggerInterceptor.UnaryInterceptor()),
grpc.StreamInterceptor(loggerInterceptor.StreamInterceptor()),
),
)
}
The interceptor will automatically enrich each log records with the x-request-id
fetch from the context metadata in
the field requestID
.
You can specify additional metadata to add to logs records:
- the key is the metadata name to fetch
- the value is the log field to fill
loggerInterceptor.Metadata(
map[string]string{
"x-some-metadata": "someMetadata",
"x-other-metadata": "otherMetadata",
},
)
You can also specify a list of gRPC methods to exclude from logging:
loggerInterceptor.Exlude("/test.Service/Unary", "/test.Service/Bidi")
Note: even if excluded, failing gRPC methods calls will still be logged for observability purposes.
This module provides a GrpcHealthCheckService, compatible with the healthcheck module:
package main
import (
"probes"
"github.com/ankorstore/yokai/grpcserver"
"github.com/ankorstore/yokai/healthcheck"
"google.golang.org/grpc/health/grpc_health_v1"
)
func main() {
checker, _ := healthcheck.NewDefaultCheckerFactory().Create(
healthcheck.WithProbe(probes.SomeProbe()), // register for startup, liveness and readiness
healthcheck.WithProbe(probes.SomeOtherProbe(), healthcheck.Liveness), // register for liveness only
)
server, _ := grpcserver.NewDefaultGrpcServerFactory().Create()
grpc_health_v1.RegisterHealthServer(server, grpcserver.NewGrpcHealthCheckService(checker))
}
This will expose the Check and Watch RPCs, suitable for k8s startup, readiness or liveness probes.
The checker will:
- run the
liveness
probes checks if the request service name containsliveness
(likekubernetes::liveness
) - or run the
readiness
probes checks if the request service name containsreadiness
(likekubernetes::readiness
) - or run the
startup
probes checks otherwise