m/p/logtree: implement WithAddedStackDepth
This is a prerequisite to easily pass over trace-based events into
logtree. It allows a testing/Test.Helper()-like mechanism to skip some
stackframes within a call tree to the logger in order to log pertinent
log origins instead of a wrapper.
Change-Id: Ida9732f8505ff4a400e689045bea318a185f7983
Reviewed-on: https://review.monogon.dev/c/monogon/+/538
Reviewed-by: Leopold Schabel <leo@nexantic.com>
diff --git a/metropolis/pkg/logtree/logtree_publisher.go b/metropolis/pkg/logtree/logtree_publisher.go
index 25dfc5a..0b945e3 100644
--- a/metropolis/pkg/logtree/logtree_publisher.go
+++ b/metropolis/pkg/logtree/logtree_publisher.go
@@ -26,10 +26,22 @@
"source.monogon.dev/metropolis/pkg/logbuffer"
)
+type leveledPublisher struct {
+ node *node
+ depth int
+}
+
// LeveledFor returns a LeveledLogger publishing interface for a given DN. An error
// may be returned if the DN is malformed.
func (l *LogTree) LeveledFor(dn DN) (LeveledLogger, error) {
- return l.nodeByDN(dn)
+ node, err := l.nodeByDN(dn)
+ if err != nil {
+ return nil, err
+ }
+ return &leveledPublisher{
+ node: node,
+ depth: 0,
+ }, nil
}
func (l *LogTree) RawFor(dn DN) (io.Writer, error) {
@@ -86,24 +98,24 @@
// data sources into leveled logging - see ExternelLeveledPayload for more
// information.
func LogExternalLeveled(l LeveledLogger, e *ExternalLeveledPayload) error {
- n, ok := l.(*node)
+ publisher, ok := l.(*leveledPublisher)
if !ok {
- return fmt.Errorf("the given LeveledLogger is not a logtree node")
+ return fmt.Errorf("the given LeveledLogger is not a *leveledPublisher")
}
p := e.sanitize()
entry := &entry{
- origin: n.dn,
+ origin: publisher.node.dn,
leveled: p,
}
- n.tree.journal.append(entry)
- n.tree.journal.notify(entry)
+ publisher.node.tree.journal.append(entry)
+ publisher.node.tree.journal.notify(entry)
return nil
}
// log builds a LeveledPayload and entry for a given message, including all related
// metadata. It will create a new entry append it to the journal, and notify all
// pertinent subscribers.
-func (n *node) logLeveled(depth int, severity Severity, msg string) {
+func (l *leveledPublisher) logLeveled(depth int, severity Severity, msg string) {
_, file, line, ok := runtime.Caller(2 + depth)
if !ok {
file = "???"
@@ -126,58 +138,65 @@
line: line,
}
e := &entry{
- origin: n.dn,
+ origin: l.node.dn,
leveled: p,
}
- n.tree.journal.append(e)
- n.tree.journal.notify(e)
+ l.node.tree.journal.append(e)
+ l.node.tree.journal.notify(e)
}
// Info implements the LeveledLogger interface.
-func (n *node) Info(args ...interface{}) {
- n.logLeveled(0, INFO, fmt.Sprint(args...))
+func (l *leveledPublisher) Info(args ...interface{}) {
+ l.logLeveled(l.depth, INFO, fmt.Sprint(args...))
}
// Infof implements the LeveledLogger interface.
-func (n *node) Infof(format string, args ...interface{}) {
- n.logLeveled(0, INFO, fmt.Sprintf(format, args...))
+func (l *leveledPublisher) Infof(format string, args ...interface{}) {
+ l.logLeveled(l.depth, INFO, fmt.Sprintf(format, args...))
}
// Warning implements the LeveledLogger interface.
-func (n *node) Warning(args ...interface{}) {
- n.logLeveled(0, WARNING, fmt.Sprint(args...))
+func (l *leveledPublisher) Warning(args ...interface{}) {
+ l.logLeveled(l.depth, WARNING, fmt.Sprint(args...))
}
// Warningf implements the LeveledLogger interface.
-func (n *node) Warningf(format string, args ...interface{}) {
- n.logLeveled(0, WARNING, fmt.Sprintf(format, args...))
+func (l *leveledPublisher) Warningf(format string, args ...interface{}) {
+ l.logLeveled(l.depth, WARNING, fmt.Sprintf(format, args...))
}
// Error implements the LeveledLogger interface.
-func (n *node) Error(args ...interface{}) {
- n.logLeveled(0, ERROR, fmt.Sprint(args...))
+func (l *leveledPublisher) Error(args ...interface{}) {
+ l.logLeveled(l.depth, ERROR, fmt.Sprint(args...))
}
// Errorf implements the LeveledLogger interface.
-func (n *node) Errorf(format string, args ...interface{}) {
- n.logLeveled(0, ERROR, fmt.Sprintf(format, args...))
+func (l *leveledPublisher) Errorf(format string, args ...interface{}) {
+ l.logLeveled(l.depth, ERROR, fmt.Sprintf(format, args...))
}
// Fatal implements the LeveledLogger interface.
-func (n *node) Fatal(args ...interface{}) {
- n.logLeveled(0, FATAL, fmt.Sprint(args...))
+func (l *leveledPublisher) Fatal(args ...interface{}) {
+ l.logLeveled(l.depth, FATAL, fmt.Sprint(args...))
}
// Fatalf implements the LeveledLogger interface.
-func (n *node) Fatalf(format string, args ...interface{}) {
- n.logLeveled(0, FATAL, fmt.Sprintf(format, args...))
+func (l *leveledPublisher) Fatalf(format string, args ...interface{}) {
+ l.logLeveled(l.depth, FATAL, fmt.Sprintf(format, args...))
+}
+
+// WithAddedStackDepth impleemnts the LeveledLogger interface.
+func (l *leveledPublisher) WithAddedStackDepth(depth int) LeveledLogger {
+ l2 := *l
+ l2.depth += depth
+ return &l2
}
// V implements the LeveledLogger interface.
-func (n *node) V(v VerbosityLevel) VerboseLeveledLogger {
+func (l *leveledPublisher) V(v VerbosityLevel) VerboseLeveledLogger {
return &verbose{
- node: n,
- enabled: n.verbosity >= v,
+ publisher: l,
+ enabled: l.node.verbosity >= v,
}
}
@@ -186,8 +205,9 @@
// VerboseLeveledLoggers must be short lived, as a changed in verbosity will not
// affect all already existing VerboseLeveledLoggers.
type verbose struct {
- node *node
- enabled bool
+ publisher *leveledPublisher
+ node *node
+ enabled bool
}
func (v *verbose) Enabled() bool {
@@ -198,12 +218,12 @@
if !v.enabled {
return
}
- v.node.logLeveled(0, INFO, fmt.Sprint(args...))
+ v.publisher.logLeveled(v.publisher.depth, INFO, fmt.Sprint(args...))
}
func (v *verbose) Infof(format string, args ...interface{}) {
if !v.enabled {
return
}
- v.node.logLeveled(0, INFO, fmt.Sprintf(format, args...))
+ v.publisher.logLeveled(v.publisher.depth, INFO, fmt.Sprintf(format, args...))
}