grpc_logrus

package
v0.0.0-...-f63a7df Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 11, 2017 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

`grpc_logrus` is a gRPC logging middleware backed by Logrus loggers

It accepts a user-configured `logrus.Entry` that will be used for logging completed gRPC calls. The same `logrus.Entry` will be used for logging completed gRPC calls, and be populated into the `context.Context` passed into gRPC handler code.

You can use `Extract` to log into a request-scoped `logrus.Entry` instance in your handler code. The fields set on the logger correspond to the grpc_ctxtags.Tags attached to the context.

This package also implements request and response *payload* logging, both for server-side and client-side. These will be logged as structured `jsonbp` 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.

Logrus can also be made as a backend for gRPC library internals. For that use `ReplaceGrpcLogger`.

Please see examples and tests for examples of use.

Example (HandlerUsageUnaryPing)

Simple unary handler that adds custom fields to the requests's context. These will be used for all log statements.

package main

import (
	"time"

	"github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus"
	"github.com/sirupsen/logrus"

	"github.com/grpc-ecosystem/go-grpc-middleware"
	"github.com/grpc-ecosystem/go-grpc-middleware/tags"
	pb_testproto "github.com/grpc-ecosystem/go-grpc-middleware/testing/testproto"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
)

// Initialization shows a relatively complex initialization sequence.
func main(logrusLogger *logrus.Logger, customFunc grpc_logrus.CodeToLevel) *grpc.Server {
	// Logrus entry is used, allowing pre-definition of certain fields by the user.
	logrusEntry := logrus.NewEntry(logrusLogger)
	// Shared options for the logger, with a custom gRPC code to log level function.
	opts := []grpc_logrus.Option{
		grpc_logrus.WithLevels(customFunc),
	}
	// Make sure that log statements internal to gRPC library are logged using the zapLogger as well.
	grpc_logrus.ReplaceGrpcLogger(logrusEntry)
	// Create a server, make sure we put the grpc_ctxtags context before everything else.
	server := grpc.NewServer(
		grpc_middleware.WithUnaryServerChain(
			grpc_ctxtags.UnaryServerInterceptor(grpc_ctxtags.WithFieldExtractor(grpc_ctxtags.CodeGenRequestFieldExtractor)),
			grpc_logrus.UnaryServerInterceptor(logrusEntry, opts...),
		),
		grpc_middleware.WithStreamServerChain(
			grpc_ctxtags.StreamServerInterceptor(grpc_ctxtags.WithFieldExtractor(grpc_ctxtags.CodeGenRequestFieldExtractor)),
			grpc_logrus.StreamServerInterceptor(logrusEntry, opts...),
		),
	)
	return server
}

func main(logrusLogger *logrus.Logger) *grpc.Server {
	// Logrus entry is used, allowing pre-definition of certain fields by the user.
	logrusEntry := logrus.NewEntry(logrusLogger)
	// Shared options for the logger, with a custom duration to log field function.
	opts := []grpc_logrus.Option{
		grpc_logrus.WithDurationField(func(duration time.Duration) (key string, value interface{}) {
			return "grpc.time_ns", duration.Nanoseconds()
		}),
	}
	server := grpc.NewServer(
		grpc_middleware.WithUnaryServerChain(
			grpc_ctxtags.UnaryServerInterceptor(),
			grpc_logrus.UnaryServerInterceptor(logrusEntry, opts...),
		),
		grpc_middleware.WithStreamServerChain(
			grpc_ctxtags.StreamServerInterceptor(),
			grpc_logrus.StreamServerInterceptor(logrusEntry, opts...),
		),
	)
	return server
}

// Simple unary handler that adds custom fields to the requests's context. These will be used for all log statements.
func main() interface{} {
	x := func(ctx context.Context, ping *pb_testproto.PingRequest) (*pb_testproto.PingResponse, error) {
		// Add fields the ctxtags of the request which will be added to all extracted loggers.
		grpc_ctxtags.Extract(ctx).Set("custom_tags.string", "something").Set("custom_tags.int", 1337)
		// Extract a request-scoped zap.Logger and log a message.
		grpc_logrus.Extract(ctx).Info("some ping")
		return &pb_testproto.PingResponse{Value: ping.Value}, nil
	}
	return x
}
Output:

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// SystemField is used in every log statement made through grpc_logrus. Can be overwritten before any initialization code.
	SystemField = "system"

	// KindField describes the log gield used to incicate whether this is a server or a client log statment.
	KindField = "span.kind"
)
View Source
var DefaultDurationToField = DurationToTimeMillisField

DefaultDurationToField is the default implementation of converting request duration to a log field (key and value).

View Source
var (
	// JsonPBMarshaller is the marshaller used for serializing protobuf messages.
	JsonPbMarshaller = &jsonpb.Marshaler{}
)

Functions

func DefaultClientCodeToLevel

func DefaultClientCodeToLevel(code codes.Code) logrus.Level

DefaultClientCodeToLevel is the default implementation of gRPC return codes to log levels for client side.

func DefaultCodeToLevel

func DefaultCodeToLevel(code codes.Code) logrus.Level

DefaultCodeToLevel is the default implementation of gRPC return codes to log levels for server side.

func DurationToDurationField

func DurationToDurationField(duration time.Duration) (key string, value interface{})

DurationToDurationField uses the duration value to log the request duration.

func DurationToTimeMillisField

func DurationToTimeMillisField(duration time.Duration) (key string, value interface{})

DurationToTimeMillisField converts the duration to milliseconds and uses the key `grpc.time_ms`.

func Extract

func Extract(ctx context.Context) *logrus.Entry

Extract takes the call-scoped logrus.Entry from grpc_logrus middleware.

If the grpc_logrus middleware wasn't used, a no-op `logrus.Entry` is returned. This makes it safe to use regardless.

func PayloadStreamClientInterceptor

func PayloadStreamClientInterceptor(entry *logrus.Entry, decider grpc_logging.ClientPayloadLoggingDecider) grpc.StreamClientInterceptor

PayloadStreamServerInterceptor returns a new streaming client interceptor that logs the paylods of requests and responses.

func PayloadStreamServerInterceptor

func PayloadStreamServerInterceptor(entry *logrus.Entry, decider grpc_logging.ServerPayloadLoggingDecider) grpc.StreamServerInterceptor

PayloadUnaryServerInterceptor returns a new server server interceptors that logs the payloads of requests.

This *only* works when placed *after* the `grpc_logrus.StreamServerInterceptor`. However, the logging can be done to a separate instance of the logger.

func PayloadUnaryClientInterceptor

func PayloadUnaryClientInterceptor(entry *logrus.Entry, decider grpc_logging.ClientPayloadLoggingDecider) grpc.UnaryClientInterceptor

PayloadUnaryClientInterceptor returns a new unary client interceptor that logs the paylods of requests and responses.

func PayloadUnaryServerInterceptor

func PayloadUnaryServerInterceptor(entry *logrus.Entry, 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 `grpc_logrus.UnaryServerInterceptor`. However, the logging can be done to a separate instance of the logger.

func ReplaceGrpcLogger

func ReplaceGrpcLogger(logger *logrus.Entry)

ReplaceGrpcLogger sets the given logrus.Logger as a gRPC-level logger. This should be called *before* any other initialization, preferably from init() functions.

func StreamClientInterceptor

func StreamClientInterceptor(entry *logrus.Entry, opts ...Option) grpc.StreamClientInterceptor

StreamServerInterceptor returns a new streaming client interceptor that optionally logs the execution of external gRPC calls.

func StreamServerInterceptor

func StreamServerInterceptor(entry *logrus.Entry, opts ...Option) grpc.StreamServerInterceptor

StreamServerInterceptor returns a new streaming server interceptor that adds logrus.Entry to the context.

func UnaryClientInterceptor

func UnaryClientInterceptor(entry *logrus.Entry, opts ...Option) grpc.UnaryClientInterceptor

UnaryClientInterceptor returns a new unary client interceptor that optionally logs the execution of external gRPC calls.

func UnaryServerInterceptor

func UnaryServerInterceptor(entry *logrus.Entry, opts ...Option) grpc.UnaryServerInterceptor

PayloadUnaryServerInterceptor returns a new unary server interceptors that adds logrus.Entry to the context.

Types

type CodeToLevel

type CodeToLevel func(code codes.Code) logrus.Level

CodeToLevel function defines the mapping between gRPC return codes and interceptor log level.

type DurationToField

type DurationToField func(duration time.Duration) (key string, value interface{})

DurationToField function defines how to produce duration fields for logging

type Option

type Option func(*options)

func WithCodes

func WithCodes(f grpc_logging.ErrorToCode) Option

WithCodes customizes the function for mapping errors to error codes.

func WithDurationField

func WithDurationField(f DurationToField) Option

WithDurationField customizes the function for mapping request durations to log fields.

func WithLevels

func WithLevels(f CodeToLevel) Option

WithLevels customizes the function for mapping gRPC return codes and interceptor log level statements.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL