Documentation ¶
Overview ¶
Package logging is a "parent" package for gRPC logging middlewares.
The gRPC logging middleware populates request-scoped data to `logging.Fields` that relate to the current gRPC call (e.g. service and method names). You can extract/inject data in the propagated context using `logging.ExtractFields` and `logging.InjectFields`.
Once the gRPC logging middleware has added the gRPC specific Fields to the ctx they will then be written with the log lines.
All logging middleware will emit a final log statement. It is based on the error returned by the handler function, the gRPC status code, an error (if any) and it emits at a level controlled via `WithLevels`. You can control this behavior using `WithDecider`.
This parent package ¶
This particular package is intended for use by other middleware, logging or otherwise. It contains interfaces that other logging middlewares *could* share. This allows code to be shared between different implementations.
Field names ¶
All field names of loggers follow the OpenTracing semantics definitions, with `grpc.` prefix if needed: https://github.com/opentracing/specification/blob/master/semantic_conventions.md
Implementations:
* providers/kit * providers/logr * providers/logrus * providers/phuslog * providers/slog * providers/zap * providers/zerolog
Index ¶
- Variables
- func DefaultErrorToCode(err error) codes.Code
- func InjectFields(ctx context.Context, f Fields) context.Context
- func InjectLogField(ctx context.Context, key string, val any) context.Context
- func StreamClientInterceptor(logger Logger, opts ...Option) grpc.StreamClientInterceptor
- func StreamServerInterceptor(logger Logger, opts ...Option) grpc.StreamServerInterceptor
- func UnaryClientInterceptor(logger Logger, opts ...Option) grpc.UnaryClientInterceptor
- func UnaryServerInterceptor(logger Logger, opts ...Option) grpc.UnaryServerInterceptor
- type CodeToLevel
- type DurationToFields
- type ErrorToCode
- type Fields
- type Level
- type LoggableEvent
- type Logger
- type LoggerFunc
- type Option
- func WithCodes(f ErrorToCode) Option
- func WithDisableLoggingFields(disableGrpcLogFields ...string) Option
- func WithDurationField(f DurationToFields) Option
- func WithFieldsFromContext(f fieldsFromCtxFn) Option
- func WithFieldsFromContextAndCallMeta(f fieldsFromCtxCallMetaFn) Option
- func WithLevels(f CodeToLevel) Option
- func WithLogOnEvents(events ...LoggableEvent) Option
- func WithTimestampFormat(format string) Option
Constants ¶
This section is empty.
Variables ¶
var ( // SystemTag is tag representing an event inside gRPC call. SystemTag = []string{"protocol", "grpc"} // ComponentFieldKey is a tag representing the client/server that is calling. ComponentFieldKey = "grpc.component" KindServerFieldValue = "server" KindClientFieldValue = "client" ServiceFieldKey = "grpc.service" MethodFieldKey = "grpc.method" MethodTypeFieldKey = "grpc.method_type" )
var DefaultDurationToFields = DurationToTimeMillisFields
DefaultDurationToFields is the default implementation of converting request duration to a field.
Functions ¶
func DefaultErrorToCode ¶
func InjectFields ¶
InjectFields allows adding fields to any existing Fields that will be used by the logging interceptor or can be extracted further in ExtractFields. For explicitness, in case of duplicates, the newest field occurrence wins. This allows nested components to update popular fields like grpc.component (e.g. server invoking gRPC client).
Don't overuse mutation of fields to avoid surprises.
func InjectLogField ¶
InjectLogField is like InjectFields, just for one field.
func StreamClientInterceptor ¶
func StreamClientInterceptor(logger Logger, opts ...Option) grpc.StreamClientInterceptor
StreamClientInterceptor returns a new streaming client interceptor that optionally logs the execution of external gRPC calls. Logger will read existing and write new logging.Fields available in current context. See `ExtractFields` and `InjectFields` for details.
func StreamServerInterceptor ¶
func StreamServerInterceptor(logger Logger, opts ...Option) grpc.StreamServerInterceptor
StreamServerInterceptor returns a new stream server interceptors that optionally logs endpoint handling. Logger will read existing and write new logging.Fields available in current context. See `ExtractFields` and `InjectFields` for details..
func UnaryClientInterceptor ¶
func UnaryClientInterceptor(logger Logger, opts ...Option) grpc.UnaryClientInterceptor
UnaryClientInterceptor returns a new unary client interceptor that optionally logs the execution of external gRPC calls. Logger will read existing and write new logging.Fields available in current context. See `ExtractFields` and `InjectFields` for details.
func UnaryServerInterceptor ¶
func UnaryServerInterceptor(logger Logger, opts ...Option) grpc.UnaryServerInterceptor
UnaryServerInterceptor returns a new unary server interceptors that optionally logs endpoint handling. Logger will read existing and write new logging.Fields available in current context. See `ExtractFields` and `InjectFields` for details.
Types ¶
type CodeToLevel ¶
CodeToLevel function defines the mapping between gRPC return codes and interceptor log level.
type DurationToFields ¶
DurationToFields function defines how to produce duration fields for logging.
type ErrorToCode ¶
ErrorToCode function determines the error code of an error. This makes using custom errors with grpc middleware easier.
type Fields ¶
type Fields []any
Fields loosely represents key value pairs that adds context to log lines. The key has to be type of string, whereas value can be an arbitrary object.
func DurationToDurationField ¶
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 DurationToTimeMillisFields ¶
DurationToTimeMillisFields converts the duration to milliseconds and uses the key `grpc.time_ms`.
func ExtractFields ¶
ExtractFields returns logging fields from the context. Fields can be added from the context using InjectFields. For example logging interceptor adds some (base) fields into context when used. If there are no fields in the context, it returns an empty Fields value. Extracted fields are useful to construct your own logger that has fields from gRPC interceptors.
func (Fields) AppendUnique ¶
AppendUnique appends (can reuse array!) fields which does not occur in existing fields slice.
func (Fields) Iterator ¶
func (f Fields) Iterator() *iter
Iterator returns iterator that allows iterating over pair of elements representing field. If number of elements is uneven, last element won't be included will be assumed as key with empty string value. If key is not string, At will panic.
func (Fields) WithUnique ¶
WithUnique returns copy of fields which is the union of all unique keys. Any duplicates in the added or current fields will be deduplicated where first occurrence takes precedence.
type Level ¶
type Level int
A Level is the importance or severity of a log event. The higher the level, the more important or severe the event.
Second, we wanted to make it easy to use levels to specify logger verbosity. Since a larger level means a more severe event, a logger that accepts events with smaller (or more negative) level means a more verbose logger. Logger verbosity is thus the negation of event severity, and the default verbosity of 0 accepts all events at least as severe as INFO.
Third, we wanted some room between levels to accommodate schemes with named levels between ours. For example, Google Cloud Logging defines a Notice level between Info and Warn. Since there are only a few of these intermediate levels, the gap between the numbers need not be large. Our gap of 4 matches OpenTelemetry's mapping. Subtracting 9 from an OpenTelemetry level in the DEBUG, INFO, WARN and ERROR ranges converts it to the corresponding slog Level range. OpenTelemetry also has the names TRACE and FATAL, which slog does not. But those OpenTelemetry levels can still be represented as slog Levels by using the appropriate integers.
Names for common levels.
func DefaultClientCodeToLevel ¶
DefaultClientCodeToLevel is the helper mapper that maps gRPC return codes to log levels for client side.
func DefaultServerCodeToLevel ¶
DefaultServerCodeToLevel is the helper mapper that maps gRPC return codes to log levels for server side.
type LoggableEvent ¶
type LoggableEvent uint
LoggableEvent defines the events a log line can be added on.
const ( // StartCall is a loggable event representing start of the gRPC call. StartCall LoggableEvent = iota // FinishCall is a loggable event representing finish of the gRPC call. FinishCall // PayloadReceived is a loggable event representing received request (server) or response (client). // Log line for this event also includes (potentially big) proto.Message of that payload in // "grpc.request.content" (server) or "grpc.response.content" (client) field. // NOTE: This can get quite verbose, especially for streaming calls, use with caution (e.g. debug only purposes). PayloadReceived // PayloadSent is a loggable event representing sent response (server) or request (client). // Log line for this event also includes (potentially big) proto.Message of that payload in // "grpc.response.content" (server) or "grpc.request.content" (client) field. // NOTE: This can get quite verbose, especially for streaming calls, use with caution (e.g. debug only purposes). PayloadSent )
type Logger ¶
Logger requires Log method, similar to experimental slog, allowing logging interceptor to be interoperable. Official adapters for popular loggers are in `provider/` directory (separate modules). It's totally ok to copy simple function implementation over. TODO(bwplotka): Once slog is official, we could use slog method directly. Currently level is copied over, so we don't depend on experimental module. interface used for all our interceptors.
type LoggerFunc ¶
LoggerFunc is a function that also implements Logger interface.
type Option ¶
type Option func(*options)
func WithCodes ¶
func WithCodes(f ErrorToCode) Option
WithCodes customizes the function for mapping errors to error codes.
func WithDisableLoggingFields ¶ added in v2.0.1
WithDisableLoggingFields disables logging of gRPC fields provided. The following are the default logging fields:
- SystemTag[0]
- ComponentFieldKey
- ServiceFieldKey
- MethodFieldKey
- MethodTypeFieldKey
Usage example - WithDisableLoggingFields(logging.MethodFieldKey, logging.MethodTypeFieldKey)
func WithDurationField ¶
func WithDurationField(f DurationToFields) Option
WithDurationField customizes the function for mapping request durations to log fields.
func WithFieldsFromContext ¶
func WithFieldsFromContext(f fieldsFromCtxFn) Option
WithFieldsFromContext allows overriding existing or adding extra fields to all log messages per given context
func WithFieldsFromContextAndCallMeta ¶ added in v2.0.1
func WithFieldsFromContextAndCallMeta(f fieldsFromCtxCallMetaFn) Option
WithFieldsFromContextAndCallMeta allows overriding existing or adding extra fields to all log messages per given context and interceptor.CallMeta
func WithLevels ¶
func WithLevels(f CodeToLevel) Option
WithLevels customizes the function for mapping gRPC return codes and interceptor log level statements.
func WithLogOnEvents ¶
func WithLogOnEvents(events ...LoggableEvent) Option
WithLogOnEvents customizes on what events the gRPC interceptor should log on.
func WithTimestampFormat ¶
WithTimestampFormat customizes the timestamps emitted in the log fields.