-
Notifications
You must be signed in to change notification settings - Fork 227
Description
/kind feature
Describe the solution you'd like
Sometimes I want to be able to add structured logging key-value pairs where an error is generated, but it isn't logged until way up the stack. It would be nice if structured logging information could be attached to the error itself, and logged with the error.
Rough proposal:
+ type StructuredError struct {
+ error
+ KeysAndValues []any
+ }
+
+ func (err StructuredError) RecursiveKeysAndValues() []any {
+ kvs := err.KeysAndValues
+ var inner *StructuredError
+ if errors.As(err.error, &inner) {
+ // When duplicate keys are present, should the inner most or outermost error win?
+ kvs = serialize.MergeKVs(inner.RecursiveKeysAndValues(), kvs)
+ }
+ return kvs
+ }
func (l *loggingT) errorS(err error, logger *logr.Logger, filter LogFilter, depth int, msg string, keysAndValues ...interface{}) {
+ var structuredErr *StructuredError
+ if errors.As(err, &structuredErr) {
+ keysAndValues = append(keysAndValues, structuredErr.RecursiveKeysAndValues()...)
+ }
if filter != nil {
msg, keysAndValues = filter.FilterS(msg, keysAndValues)
}
if logger != nil {
logger.WithCallDepth(depth+2).Error(err, msg, keysAndValues...)
return
}
l.printS(err, severity.ErrorLog, depth+1, msg, keysAndValues...)
}Open Question: should the message returned by structuredErr.Error() include the keyvalue pairs? In that case they should be omitted from the message when logged with klog, but that gets complicated when you have a non-structured error wrapping a structured error wrapping a non-structured error. My inclination is to not include them in the default Error() message for this reason.
Open Question: should the StructuredError type be hoisted to logr? cc @thockin