Documentation
¶
Overview ¶
Package ctxd defines contextualized structured logging and error handling.
Index ¶
- func AddFields(ctx context.Context, keysAndValues ...interface{}) context.Context
- func ClearFields(ctx context.Context) context.Context
- func Fields(ctx context.Context) []interface{}
- func IsDebug(ctx context.Context) bool
- func LogError(ctx context.Context, err error, l LogFunc)
- func LogWriter(ctx context.Context) io.Writer
- func NewError(ctx context.Context, message string, keysAndValues ...interface{}) error
- func WithDebug(ctx context.Context) context.Context
- func WithLogWriter(ctx context.Context, w io.Writer) context.Context
- func WrapError(ctx context.Context, err error, message string, keysAndValues ...interface{}) error
- type DeferredJSON
- type DeferredString
- type LogFunc
- type Logger
- type LoggerMock
- func (m *LoggerMock) Debug(ctx context.Context, msg string, keysAndValues ...interface{})
- func (m *LoggerMock) Error(ctx context.Context, msg string, keysAndValues ...interface{})
- func (m *LoggerMock) Important(ctx context.Context, msg string, keysAndValues ...interface{})
- func (m *LoggerMock) Info(ctx context.Context, msg string, keysAndValues ...interface{})
- func (m *LoggerMock) Warn(ctx context.Context, msg string, keysAndValues ...interface{})
- type LoggerProvider
- type NoOpLogger
- func (NoOpLogger) CtxdLogger() Logger
- func (NoOpLogger) Debug(_ context.Context, _ string, _ ...interface{})
- func (NoOpLogger) Error(_ context.Context, _ string, _ ...interface{})
- func (NoOpLogger) Important(_ context.Context, _ string, _ ...interface{})
- func (NoOpLogger) Info(_ context.Context, _ string, _ ...interface{})
- func (NoOpLogger) Warn(_ context.Context, _ string, _ ...interface{})
- type StructuredError
- type Tuples
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AddFields ¶
AddFields returns context with added loosely-typed key-value pairs as fields.
If key-value pairs exist in parent context already, new pairs are appended.
Example ¶
package main
import (
"context"
"fmt"
"github.com/bool64/ctxd"
)
func main() {
logger := ctxd.LoggerMock{}
// Once instrumented context can aid logger with structured information.
ctx := ctxd.AddFields(context.Background(), "foo", "bar")
logger.Info(ctx, "something happened")
// Also context contributes additional information to structured errors.
err := ctxd.NewError(ctx, "something failed", "baz", "quux")
ctxd.LogError(ctx, err, logger.Error)
fmt.Print(logger.String())
}
Output: info: something happened {"foo":"bar"} error: something failed {"baz":"quux","foo":"bar"}
func ClearFields ¶
ClearFields returns context without any fields.
func LogError ¶
LogError pushes error value to a contextualized logger method.
If err is nil, LogError produces no operation. LogError function matches Logger methods, e.g. Error.
func NewError ¶
NewError creates error with optional structured data.
LogError fields from context are also added to error structured data.
func WithLogWriter ¶
WithLogWriter returns context with custom log writer. Can be useful to write logs into response stream.
func WrapError ¶
WrapError returns an error annotated with message and structured data.
If err is nil, WrapError returns nil. LogError fields from context are also added to error structured data.
Example ¶
package main
import (
"context"
"errors"
"fmt"
"github.com/bool64/ctxd"
)
func main() {
ctx := context.Background()
// Elaborate context with fields.
ctx = ctxd.AddFields(ctx,
"field1", 1,
"field2", "abc",
)
// Add more fields when creating error.
err := ctxd.NewError(ctx, "something failed",
"field3", 3.0,
)
err2 := ctxd.WrapError(
// You can use same or any other context when wrapping error.
ctxd.AddFields(context.Background(), "field5", "V"),
err, "wrapped",
"field4", true)
// Setup your logger.
var (
lm = ctxd.LoggerMock{}
logger ctxd.Logger = &lm
)
// Inspect error fields.
var se ctxd.StructuredError
if errors.As(err, &se) {
fmt.Printf("error fields: %v\n", se.Fields())
}
// Log errors.
ctxd.LogError(ctx, err, logger.Error)
ctxd.LogError(ctx, err2, logger.Warn)
fmt.Print(lm.String())
}
Output: error fields: map[field1:1 field2:abc field3:3] error: something failed {"field1":1,"field2":"abc","field3":3} warn: wrapped: something failed {"field1":1,"field2":"abc","field3":3,"field4":true,"field5":"V"}
Types ¶
type DeferredJSON ¶
type DeferredJSON func() interface{}
DeferredJSON postpones log field processing, suitable for debug logging.
func (DeferredJSON) MarshalJSON ¶
func (d DeferredJSON) MarshalJSON() ([]byte, error)
MarshalJSON implements json.Marshaler.
type DeferredString ¶
type DeferredString func() interface{}
DeferredString postpones log field processing, suitable for debug logging.
func (DeferredString) String ¶
func (d DeferredString) String() string
String implements fmt.Stringer.
type Logger ¶
type Logger interface {
// Debug logs a message.
Debug(ctx context.Context, msg string, keysAndValues ...interface{})
// Info logs a message.
Info(ctx context.Context, msg string, keysAndValues ...interface{})
// Important forcibly logs an important message with level INFO disregarding logger level constraints.
// Can be used for logging historically important information.
Important(ctx context.Context, msg string, keysAndValues ...interface{})
// Warn logs a message.
Warn(ctx context.Context, msg string, keysAndValues ...interface{})
// Error logs a message.
Error(ctx context.Context, msg string, keysAndValues ...interface{})
}
Logger is a contextualized structured logger.
Logging methods accept keys and values as variadic argument that contains loosely-typed key-value pairs. When processing pairs, the first element of the pair is used as the field key and the second as the field value.
func LoggerWithFields ¶
LoggerWithFields instruments contextualized logger with global fields.
Example ¶
package main
import (
"context"
"fmt"
"github.com/bool64/ctxd"
)
func main() {
lm := ctxd.LoggerMock{}
var globalLogger ctxd.Logger = &lm
localLogger := ctxd.LoggerWithFields(globalLogger, "local", 123)
ctx1 := ctxd.AddFields(context.Background(),
"ctx", 1,
"foo", "bar",
)
ctx2 := ctxd.AddFields(context.Background(), "ctx", 2)
localLogger.Info(ctx1, "hello", "he", "lo")
localLogger.Warn(ctx2, "bye", "by", "ee")
fmt.Print(lm.String())
}
Output: info: hello {"ctx":1,"foo":"bar","he":"lo","local":123} warn: bye {"by":"ee","ctx":2,"local":123}
type LoggerMock ¶ added in v0.1.2
type LoggerMock struct {
bytes.Buffer
OnError func(err error)
// contains filtered or unexported fields
}
LoggerMock logs messages to internal buffer.
func (*LoggerMock) Debug ¶ added in v0.1.2
func (m *LoggerMock) Debug(ctx context.Context, msg string, keysAndValues ...interface{})
Debug logs a message.
func (*LoggerMock) Error ¶ added in v0.1.2
func (m *LoggerMock) Error(ctx context.Context, msg string, keysAndValues ...interface{})
Error logs a message.
func (*LoggerMock) Important ¶ added in v0.1.2
func (m *LoggerMock) Important(ctx context.Context, msg string, keysAndValues ...interface{})
Important logs a message.
type LoggerProvider ¶
type LoggerProvider interface {
CtxdLogger() Logger
}
LoggerProvider is an embeddable provider interface.
type NoOpLogger ¶
type NoOpLogger struct{}
NoOpLogger is a contextualized logger stub.
func (NoOpLogger) Debug ¶
func (NoOpLogger) Debug(_ context.Context, _ string, _ ...interface{})
Debug discards debug message.
func (NoOpLogger) Error ¶
func (NoOpLogger) Error(_ context.Context, _ string, _ ...interface{})
Error discards error message.
func (NoOpLogger) Important ¶
func (NoOpLogger) Important(_ context.Context, _ string, _ ...interface{})
Important discards important message.
type StructuredError ¶
type StructuredError interface {
// Error returns message of error.
Error() string
// Tuples returns structured data of error in form of loosely-typed key-value pairs.
Tuples() []interface{}
// Fields returns structured data of error as a map.
Fields() map[string]interface{}
}
StructuredError defines error with message and data.