logging

package
v0.50.0-rc0 Latest Latest
Warning

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

Go to latest
Published: Nov 11, 2024 License: AGPL-3.0 Imports: 31 Imported by: 162

Documentation

Overview

Package logging package contains functionality for viam-server logging.

Index

Constants

View Source
const DefaultTimeFormatStr = "2006-01-02T15:04:05.000Z0700"

DefaultTimeFormatStr is the default time format string for log appenders.

Variables

View Source
var (

	// GlobalLogLevel should be used whenever a zap logger is created that wants to obey the debug
	// flag from the CLI or robot config.
	GlobalLogLevel = zap.NewAtomicLevelAt(zap.InfoLevel)
)

Functions

func CreateNewGRPCClient added in v0.13.0

func CreateNewGRPCClient(ctx context.Context, cloudCfg *CloudConfig, logger Logger) (rpc.ClientConn, error)

CreateNewGRPCClient creates a new grpc cloud configured to communicate with the robot service based on the cloud config given.

func EnableDebugMode added in v0.16.0

func EnableDebugMode(ctx context.Context) context.Context

EnableDebugMode returns a new context with debug logging state attached with a randomly generated log key.

func EnableDebugModeWithKey added in v0.16.0

func EnableDebugModeWithKey(ctx context.Context, debugLogKey string) context.Context

EnableDebugModeWithKey returns a new context with debug logging state attached. An empty `debugLogKey` generates a random value.

func FieldFromProto added in v0.47.0

func FieldFromProto(field *structpb.Struct) (zap.Field, error)

FieldFromProto unmarshals a proto-encoded zap.Field.

func FieldKeyAndValueFromProto added in v0.23.0

func FieldKeyAndValueFromProto(field *structpb.Struct) (string, any, error)

FieldKeyAndValueFromProto examines a *structpb.Struct and returns its key string and native golang value.

func FieldToProto added in v0.23.0

func FieldToProto(field zap.Field) (*structpb.Struct, error)

FieldToProto converts a zap.Field to a *structpb.Struct.

func GetName added in v0.16.0

func GetName(ctx context.Context) string

GetName returns the debug log key included when enabling the context for debug logging.

func IsDebugMode added in v0.16.0

func IsDebugMode(ctx context.Context) bool

IsDebugMode returns whether the input context has debug logging enabled.

func NewLoggerWithRegistry added in v0.43.0

func NewLoggerWithRegistry(name string) (Logger, *Registry)

NewLoggerWithRegistry is the same as NewLogger but also returns the associated Registry.

func NewObservedTestLoggerWithRegistry added in v0.43.0

func NewObservedTestLoggerWithRegistry(tb testing.TB, name string) (Logger, *observer.ObservedLogs, *Registry)

NewObservedTestLoggerWithRegistry is like NewObservedTestLogger but also returns the associated registry. It also takes a name for the logger.

func NewZapLoggerConfig added in v0.13.0

func NewZapLoggerConfig() zap.Config

NewZapLoggerConfig returns a new default logger config.

func ReplaceGlobal added in v0.12.0

func ReplaceGlobal(logger Logger)

ReplaceGlobal replaces the global loggers.

func UnaryClientInterceptor added in v0.16.0

func UnaryClientInterceptor(
	ctx context.Context,
	method string,
	req, reply interface{},
	cc *grpc.ClientConn,
	invoker grpc.UnaryInvoker,
	opts ...grpc.CallOption,
) error

UnaryClientInterceptor adds debug directives from the current context (if any) to the outgoing request's metadata.

func UnaryServerInterceptor added in v0.16.0

func UnaryServerInterceptor(
	ctx context.Context,
	req interface{},
	info *grpc.UnaryServerInfo,
	handler grpc.UnaryHandler,
) (interface{}, error)

UnaryServerInterceptor checks the incoming RPC metadata for a distributed tracing directive and attaches any information to a debug context.

Types

type Appender added in v0.13.0

type Appender interface {
	// Write submits a structured log entry to the appender for logging.
	Write(zapcore.Entry, []zapcore.Field) error
	// Sync is for signaling that any buffered logs to `Write` should be flushed. E.g: at shutdown.
	Sync() error
}

Appender is an output for log entries. This is a subset of the `zapcore.Core` interface.

func NewTestAppender added in v0.20.0

func NewTestAppender(tb testing.TB) Appender

NewTestAppender returns a logger appender that logs to the underlying `testing.TB` object. Writing logs with `tb.Log` does two things:

  • Prepends the log with the filename/line number that called the `tb.Log` method. This is not useful to us.
  • Correctly associates the log line with a Golang "Test*" function.

Additionally, this test appender will log in the local/machine timezone.

For tests that run in series (i.e: do not call `t.Parallel()`), writing to stdout (i.e: `fmt.Print`) this does not matter. Go's best effort detection works fine. But for tests running in parallel, the best-effort algorithm can map log lines to the wrong test. This is most noticeable when json logging is enabled. Where each log line has its test name, e.g:

{"Time":"2024-01-23T09:26:57.843619918-05:00","Action":"output","Package":"go.viam.com/rdk/robot","Test":"TestSessions/window_size=2s","Output":"local_robot.go:760: 2024-01-23T09:26:57.843-0500\tDEBUG\t\timpl/local_robot.go:760\thandlingweak update for..."}

A note about the filename/line that Go prepends to these test logs. Go normally finds this by walking up a couple stack frames to discover where a call to `t.Log` came from. However, it's not our desire for that to refer to the `tapp.tb.Log` call from the `testAppender.Write` method below. Go exposes a `tb.Helper()` method for this. All functions that call `tb.Helper` will add their stack frame to a filter. Go will walk up and report the first filename/line number from the first method that does not exempt itself.

Notably, zap's testing logger has a bug in this regard. Due to forgetting a `tb.Helper` call, test logs through their library always include `logger.go:130` instead of the actual log line.

type AtomicLevel added in v0.13.0

type AtomicLevel struct {
	// contains filtered or unexported fields
}

AtomicLevel is a level that can be concurrently accessed.

func NewAtomicLevelAt added in v0.13.0

func NewAtomicLevelAt(initLevel Level) AtomicLevel

NewAtomicLevelAt creates a new AtomicLevel at the input `initLevel`.

func (AtomicLevel) Get added in v0.13.0

func (level AtomicLevel) Get() Level

Get returns the level.

func (AtomicLevel) Set added in v0.13.0

func (level AtomicLevel) Set(newLevel Level)

Set changes the level.

type CloudConfig added in v0.13.0

type CloudConfig struct {
	AppAddress string
	ID         string
	Secret     string
}

CloudConfig contains the necessary inputs to send logs to the app backend over grpc.

type ConsoleAppender added in v0.13.0

type ConsoleAppender struct {
	io.Writer
}

ConsoleAppender will create human readable lines from log events and write them to the desired output sync. E.g: stdout or a file.

func NewStdoutAppender added in v0.13.0

func NewStdoutAppender() ConsoleAppender

NewStdoutAppender creates a new appender that prints to stdout.

func NewWriterAppender added in v0.13.0

func NewWriterAppender(writer io.Writer) ConsoleAppender

NewWriterAppender creates a new appender that prints to the input writer.

func (ConsoleAppender) Sync added in v0.13.0

func (appender ConsoleAppender) Sync() error

Sync is a no-op.

func (ConsoleAppender) Write added in v0.13.0

func (appender ConsoleAppender) Write(entry zapcore.Entry, fields []zapcore.Field) error

Write outputs the log entry to the underlying stream.

type Level

type Level int

Level is an enum of log levels. Its value can be `DEBUG`, `INFO`, `WARN` or `ERROR`.

const (

	// DEBUG log level.
	DEBUG Level = iota - 1
	// INFO log level.
	INFO
	// WARN log level.
	WARN
	// ERROR log level.
	ERROR
)

func LevelFromString

func LevelFromString(inp string) (Level, error)

LevelFromString parses an input string to a log level. The string must be one of `debug`, `info`, `warn`, `warning`, or `error`. The parsing is case-insensitive. An error is returned if the input does not match one of labeled cases.

func (Level) AsZap added in v0.13.0

func (level Level) AsZap() zapcore.Level

AsZap converts the Level to a `zapcore.Level`.

func (Level) MarshalJSON

func (level Level) MarshalJSON() ([]byte, error)

MarshalJSON converts a log level to a json string.

func (Level) String

func (level Level) String() string

func (*Level) UnmarshalJSON

func (level *Level) UnmarshalJSON(data []byte) (err error)

UnmarshalJSON converts a json string to a log level.

type LogEntry added in v0.13.0

type LogEntry struct {
	zapcore.Entry
	// Fields are the key-value fields of the entry.
	Fields []zapcore.Field
}

LogEntry embeds a zapcore Entry and slice of Fields.

type Logger added in v0.12.0

type Logger interface {
	ZapCompatibleLogger

	SetLevel(level Level)
	GetLevel() Level
	Sublogger(subname string) Logger
	AddAppender(appender Appender)
	AsZap() *zap.SugaredLogger
	// Unconditionally logs a LogEntry object. Specifically any configured log level is ignored.
	Write(*LogEntry)
	WithFields(args ...interface{}) Logger

	CDebug(ctx context.Context, args ...interface{})
	CDebugf(ctx context.Context, template string, args ...interface{})
	CDebugw(ctx context.Context, msg string, keysAndValues ...interface{})

	CInfo(ctx context.Context, args ...interface{})
	CInfof(ctx context.Context, template string, args ...interface{})
	CInfow(ctx context.Context, msg string, keysAndValues ...interface{})

	CWarn(ctx context.Context, args ...interface{})
	CWarnf(ctx context.Context, template string, args ...interface{})
	CWarnw(ctx context.Context, msg string, keysAndValues ...interface{})

	CError(ctx context.Context, args ...interface{})
	CErrorf(ctx context.Context, template string, args ...interface{})
	CErrorw(ctx context.Context, msg string, keysAndValues ...interface{})
}

Logger interface for logging to.

func FromZapCompatible added in v0.12.0

func FromZapCompatible(logger ZapCompatibleLogger) Logger

FromZapCompatible upconverts a ZapCompatibleLogger to a logging.Logger. If the argument already satisfies logging.Logger, no changes will be made. A nil input returns a nil logger. An input of unknown type will create a new logger that's not associated with the input.

func Global added in v0.12.0

func Global() Logger

Global returns the global logger.

func NewBlankLogger added in v0.13.0

func NewBlankLogger(name string) Logger

NewBlankLogger returns a new logger that outputs Debug+ logs in UTC, but without any pre-existing appenders/outputs.

func NewDebugLogger added in v0.12.0

func NewDebugLogger(name string) Logger

NewDebugLogger returns a new logger that outputs Debug+ logs to stdout in UTC.

func NewLogger added in v0.12.0

func NewLogger(name string) Logger

NewLogger returns a new logger that outputs Info+ logs to stdout in UTC.

func NewObservedTestLogger added in v0.12.0

func NewObservedTestLogger(tb testing.TB) (Logger, *observer.ObservedLogs)

NewObservedTestLogger is like NewTestLogger but also saves logs to an in memory observer.

func NewTestLogger added in v0.12.0

func NewTestLogger(tb testing.TB) Logger

NewTestLogger returns a new logger that outputs Debug+ logs to stdout in local time.

type LoggerPatternConfig added in v0.34.0

type LoggerPatternConfig struct {
	Pattern string `json:"pattern"`
	Level   string `json:"level"`
}

LoggerPatternConfig is an instance of a level specification for a given logger.

type MemLogger added in v0.30.0

type MemLogger struct {
	Logger

	Observer *observer.ObservedLogs
	// contains filtered or unexported fields
}

MemLogger stores test logs in memory. And can write them on request with `OutputLogs`.

func NewInMemoryLogger added in v0.30.0

func NewInMemoryLogger(tb testing.TB) *MemLogger

NewInMemoryLogger creates a MemLogger that buffers test logs and only outputs them if requested or if the test fails. This is handy if a test is noisy, but the output is useful when the test fails.

func (*MemLogger) OutputLogs added in v0.30.0

func (memLogger *MemLogger) OutputLogs()

OutputLogs writes in-memory logs to the test object MemLogger was constructed with.

type NetAppender added in v0.13.0

type NetAppender struct {
	// contains filtered or unexported fields
}

NetAppender can send log events to the app backend.

func NewNetAppender added in v0.13.0

func NewNetAppender(
	config *CloudConfig,
	conn rpc.ClientConn,
	sharedConn bool,
	loggerWithoutNet Logger,
) (*NetAppender, error)

NewNetAppender creates a NetAppender to send log events to the app backend. NetAppenders ought to be `Close`d prior to shutdown to flush remaining logs. Pass `nil` for `conn` if you want this to create its own connection.

func (*NetAppender) Check added in v0.13.0

func (nl *NetAppender) Check(entry zapcore.Entry, checkedEntry *zapcore.CheckedEntry) *zapcore.CheckedEntry

Check checks if the entry should be logged. If so, add it to the CheckedEntry list of cores.

func (*NetAppender) Close added in v0.13.0

func (nl *NetAppender) Close()

Close the NetAppender. This makes a best effort at sending all logs before returning.

func (*NetAppender) Enabled added in v0.13.0

func (nl *NetAppender) Enabled(level zapcore.Level) bool

Enabled returns if the NetAppender serving as a `zapcore.Core` should log.

func (*NetAppender) SetConn added in v0.31.0

func (nl *NetAppender) SetConn(conn rpc.ClientConn, sharedConn bool)

SetConn sets the GRPC connection used by the NetAppender. sharedConn should be true in all external calls to this. If sharedConn=false, the NetAppender will close the connection in Close(). conn may be nil.

func (*NetAppender) Sync added in v0.13.0

func (nl *NetAppender) Sync() error

Sync is a no-op. sync is not exposed as multiple calls at the same time will cause double logs and panics.

func (*NetAppender) With added in v0.13.0

func (nl *NetAppender) With(f []zapcore.Field) zapcore.Core

With creates a zapcore.Core that will log like a `NetAppender` but with extra fields attached.

func (*NetAppender) Write added in v0.13.0

func (nl *NetAppender) Write(e zapcore.Entry, f []zapcore.Field) error

type Registry added in v0.43.0

type Registry struct {
	// contains filtered or unexported fields
}

Registry is a registry of loggers. It is stored on a logger, and holds a map of known subloggers (`loggers`) and a slice of configuration objects (`logConfig`).

func (*Registry) AddAppenderToAll added in v0.47.0

func (lr *Registry) AddAppenderToAll(appender Appender)

AddAppenderToAll adds the specified appender to all loggers in the registry.

func (*Registry) GetCurrentConfig added in v0.43.0

func (lr *Registry) GetCurrentConfig() []LoggerPatternConfig

GetCurrentConfig gets the current config.

func (*Registry) Update added in v0.43.0

func (lr *Registry) Update(logConfig []LoggerPatternConfig, warnLogger Logger) error

Update updates the logger registry with the passed in `logConfig`. Invalid patterns are warn-logged through the warnLogger.

type ZapCompatibleLogger added in v0.12.0

type ZapCompatibleLogger interface {
	Desugar() *zap.Logger
	Level() zapcore.Level
	Named(name string) *zap.SugaredLogger
	Sync() error
	WithOptions(opts ...zap.Option) *zap.SugaredLogger

	Debug(args ...interface{})
	Debugf(template string, args ...interface{})
	Debugw(msg string, keysAndValues ...interface{})

	Info(args ...interface{})
	Infof(template string, args ...interface{})
	Infow(msg string, keysAndValues ...interface{})

	Warn(args ...interface{})
	Warnf(template string, args ...interface{})
	Warnw(msg string, keysAndValues ...interface{})

	Error(args ...interface{})
	Errorf(template string, args ...interface{})
	Errorw(msg string, keysAndValues ...interface{})

	Fatal(args ...interface{})
	Fatalf(template string, args ...interface{})
	Fatalw(msg string, keysAndValues ...interface{})
}

ZapCompatibleLogger is a backwards compatibility layer for existing usages of the RDK as a library for Go application code or modules. Public (to the library) methods that take a logger as input should accept this type and upconvert to a Logger via a call to `FromZapCompatible`.

Jump to

Keyboard shortcuts

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