Package kit
`grpc_kit` is a gRPC logging middleware backed by go-kit loggers
It accepts a user-configured `log.Logger` that will be used for logging completed gRPC calls,
and be populated into the `context.Context` passed into gRPC handler code.
On calling `StreamServerInterceptor` or `UnaryServerInterceptor` this logging middleware will add gRPC call information
to the ctx so that it will be present on subsequent use of the `ctxkit` logger.
If a deadline is present on the gRPC request the grpc.request.deadline tag is populated when the request begins. grpc.request.deadline
is a string representing the time (RFC3339) when the current call will expire.
This package also implements request and response *payload* logging, both for server-side and client-side. These will be
logged as structured `jsonpb` fields for every message received/sent (both unary and streaming). For that please use
`Payload*Interceptor` functions for that. Please note that the user-provided function that determines whetether to log
the full request/response payload needs to be written with care, this can significantly slow down gRPC.
*Server Interceptor*
Below is a JSON formatted example of a log that would be logged by the server interceptor:
{
"level": "info", // string log level
"msg": "finished unary call", // string log message
"grpc.code": "OK", // string grpc status code
"grpc.method": "Ping", // string method name
"grpc.service": "mwitkow.testproto.TestService", // string full name of the called service
"grpc.start_time": "2006-01-02T15:04:05Z07:00", // string RFC3339 representation of the start time
"grpc.request.deadline": "2006-01-02T15:04:05Z07:00", // string RFC3339 deadline of the current request if supplied
"grpc.request.value": "something", // string value on the request
"grpc.time_ms": 1.345, // float32 run time of the call in ms
"peer.address": {
"IP": "127.0.0.1", // string IP address of calling party
"Port": 60216, // int port call is coming in on
"Zone": "" // string peer zone for caller
},
"span.kind": "server", // string client | server
"system": "grpc" // string
"custom_field": "custom_value", // string user defined field
"custom_tags.int": 1337, // int user defined tag on the ctx
"custom_tags.string": "something", // string user defined tag on the ctx
}
*Payload Interceptor*
Below is a JSON formatted example of a log that would be logged by the payload interceptor:
{
"level": "info", // string kit log levels
"msg": "client request payload logged as grpc.request.content", // string log message
"grpc.request.content": { // object content of RPC request
"msg" : { // object kit specific inner object
"value": "something", // string defined by caller
"sleepTimeMs": 9999 // int defined by caller
}
},
"grpc.method": "Ping", // string method being called
"grpc.service": "mwitkow.testproto.TestService", // string service being called
"span.kind": "client", // string client | server
"system": "grpc" // string
}
Please see examples and tests for examples of use.
▹ Example (Initialization)
▾ Example (Initialization)
Initialization shows a relatively complex initialization sequence.
Code:
logger := log.NewNopLogger()
opts := []kit.Option{
kit.WithLevels(customFunc),
}
_ = grpc.NewServer(
grpc_middleware.WithUnaryServerChain(
grpc_ctxtags.UnaryServerInterceptor(grpc_ctxtags.WithFieldExtractor(grpc_ctxtags.CodeGenRequestFieldExtractor)),
kit.UnaryServerInterceptor(logger, opts...),
),
grpc_middleware.WithStreamServerChain(
grpc_ctxtags.StreamServerInterceptor(grpc_ctxtags.WithFieldExtractor(grpc_ctxtags.CodeGenRequestFieldExtractor)),
kit.StreamServerInterceptor(logger, opts...),
),
)
▹ Example (InitializationWithDurationFieldOverride)
▾ Example (InitializationWithDurationFieldOverride)
Code:
logger := log.NewNopLogger()
opts := []kit.Option{
kit.WithDurationField(func(duration time.Duration) []interface{} {
return kit.DurationToTimeMillisField(duration)
}),
}
_ = grpc.NewServer(
grpc_middleware.WithUnaryServerChain(
grpc_ctxtags.UnaryServerInterceptor(),
kit.UnaryServerInterceptor(logger, opts...),
),
grpc_middleware.WithStreamServerChain(
grpc_ctxtags.StreamServerInterceptor(),
kit.StreamServerInterceptor(logger, opts...),
),
)
- Variables
- func DefaultClientCodeToLevel(code codes.Code, logger log.Logger) log.Logger
- func DefaultCodeToLevel(code codes.Code, logger log.Logger) log.Logger
- func DurationToDurationField(duration time.Duration) []interface{}
- func DurationToTimeMillisField(duration time.Duration) []interface{}
- func PayloadStreamClientInterceptor(logger log.Logger, decider grpc_logging.ClientPayloadLoggingDecider) grpc.StreamClientInterceptor
- func PayloadStreamServerInterceptor(logger log.Logger, decider grpc_logging.ServerPayloadLoggingDecider) grpc.StreamServerInterceptor
- func PayloadUnaryClientInterceptor(logger log.Logger, decider grpc_logging.ClientPayloadLoggingDecider) grpc.UnaryClientInterceptor
- func PayloadUnaryServerInterceptor(logger log.Logger, decider grpc_logging.ServerPayloadLoggingDecider) grpc.UnaryServerInterceptor
- func StreamClientInterceptor(logger log.Logger, opts ...Option) grpc.StreamClientInterceptor
- func StreamServerInterceptor(logger log.Logger, opts ...Option) grpc.StreamServerInterceptor
- func UnaryClientInterceptor(logger log.Logger, opts ...Option) grpc.UnaryClientInterceptor
- func UnaryServerInterceptor(logger log.Logger, opts ...Option) grpc.UnaryServerInterceptor
- type CodeToLevel
- type DurationToField
- type Option
- func WithCodes(f grpc_logging.ErrorToCode) Option
- func WithDecider(f grpc_logging.Decider) Option
- func WithDurationField(f DurationToField) Option
- func WithLevels(f CodeToLevel) Option
- func WithTimestampFormat(format string) Option
Package files
client_interceptors.go
doc.go
options.go
payload_interceptors.go
server_interceptors.go
Variables
var (
SystemField = "grpc"
ServerField = "server"
)
DefaultDurationToField is the default implementation of converting request duration to a kit field.
var DefaultDurationToField = DurationToTimeMillisField
var (
JsonPbMarshaller grpc_logging.JsonPbMarshaler = &jsonpb.Marshaler{}
)
func DefaultClientCodeToLevel(code codes.Code, logger log.Logger) log.Logger
DefaultClientCodeToLevel is the default implementation of gRPC return codes to log levels for client side.
func DefaultCodeToLevel(code codes.Code, logger log.Logger) log.Logger
DefaultCodeToLevel is the default implementation of gRPC return codes and interceptor log level for server side.
func DurationToDurationField(duration time.Duration) []interface{}
DurationToDurationField uses a Duration field to log the request duration
and leaves it up to Log's encoder settings to determine how that is output.
func DurationToTimeMillisField(duration time.Duration) []interface{}
DurationToTimeMillisField converts the duration to milliseconds and uses the key `grpc.time_ms`.
func PayloadStreamClientInterceptor(logger log.Logger, decider grpc_logging.ClientPayloadLoggingDecider) grpc.StreamClientInterceptor
PayloadStreamClientInterceptor returns a new streaming client interceptor that logs the paylods of requests and responses.
func PayloadStreamServerInterceptor(logger log.Logger, decider grpc_logging.ServerPayloadLoggingDecider) grpc.StreamServerInterceptor
PayloadStreamServerInterceptor returns a new server server interceptors that logs the payloads of requests.
This *only* works when placed *after* the `kit.StreamServerInterceptor`. However, the logging can be done to a
separate instance of the logger.
func PayloadUnaryClientInterceptor(logger log.Logger, decider grpc_logging.ClientPayloadLoggingDecider) grpc.UnaryClientInterceptor
PayloadUnaryClientInterceptor returns a new unary client interceptor that logs the paylods of requests and responses.
func PayloadUnaryServerInterceptor(logger log.Logger, decider grpc_logging.ServerPayloadLoggingDecider) grpc.UnaryServerInterceptor
PayloadUnaryServerInterceptor returns a new unary server interceptors that logs the payloads of requests.
This *only* works when placed *after* the `kit.UnaryServerInterceptor`. However, the logging can be done to a
separate instance of the logger.
func StreamClientInterceptor(logger log.Logger, opts ...Option) grpc.StreamClientInterceptor
StreamClientInterceptor returns a new streaming client interceptor that optionally logs the execution of external gRPC calls.
func StreamServerInterceptor(logger log.Logger, opts ...Option) grpc.StreamServerInterceptor
StreamServerInterceptor returns a new stream server interceptors that adds kit.Logger to the context.
func UnaryClientInterceptor(logger log.Logger, opts ...Option) grpc.UnaryClientInterceptor
UnaryClientInterceptor returns a new unary client interceptor that optionally logs the execution of external gRPC calls.
func UnaryServerInterceptor(logger log.Logger, opts ...Option) grpc.UnaryServerInterceptor
UnaryServerInterceptor returns a new unary server interceptors that adds kit.Logger to the context.
CodeToLevel function defines the mapping between gRPC return codes and interceptor log level.
type CodeToLevel func(code codes.Code, logger log.Logger) log.Logger
DurationToField function defines how to produce duration fields for logging
type DurationToField func(duration time.Duration) []interface{}
type Option func(*options)
func WithCodes(f grpc_logging.ErrorToCode) Option
WithCodes customizes the function for mapping errors to error codes.
func WithDecider(f grpc_logging.Decider) Option
WithDecider customizes the function for deciding if the gRPC interceptor logs should log.
▾ Example
Code:
opts := []kit.Option{
kit.WithDecider(func(methodFullName string, err error) bool {
if err == nil && methodFullName == "blah.foo.healthcheck" {
return false
}
return true
}),
}
_ = []grpc.ServerOption{
grpc_middleware.WithStreamServerChain(
grpc_ctxtags.StreamServerInterceptor(),
kit.StreamServerInterceptor(log.NewNopLogger(), opts...)),
grpc_middleware.WithUnaryServerChain(
grpc_ctxtags.UnaryServerInterceptor(),
kit.UnaryServerInterceptor(log.NewNopLogger(), opts...)),
}
func WithDurationField(f DurationToField) Option
WithDurationField customizes the function for mapping request durations to log fields.
func WithLevels(f CodeToLevel) Option
WithLevels customizes the function for mapping gRPC return codes and interceptor log level statements.
func WithTimestampFormat(format string) Option
WithTimestampFormat customizes the timestamps emitted in the log fields.
Subdirectories
Name |
Synopsis |
.. |
ctxkit
|
`ctxkit` is a ctxlogger that is backed by go-kit
|