core: replace zap with logtree

Test Plan: Effective refactor. Only tests that could be affected are e2e tests that should continue to run, because we still are logging into the qemu console, even if differently.

X-Origin-Diff: phab/D642
GitOrigin-RevId: 0f12b1bc985af08a3cc269569273184321763e4b
diff --git a/core/internal/common/supervisor/BUILD.bazel b/core/internal/common/supervisor/BUILD.bazel
index ca8b513..9f940f0 100644
--- a/core/internal/common/supervisor/BUILD.bazel
+++ b/core/internal/common/supervisor/BUILD.bazel
@@ -12,9 +12,9 @@
     importpath = "git.monogon.dev/source/nexantic.git/core/internal/common/supervisor",
     visibility = ["//core:__subpackages__"],
     deps = [
+        "//core/pkg/logtree:go_default_library",
         "@com_github_cenkalti_backoff_v4//:go_default_library",
         "@org_golang_google_grpc//:go_default_library",
-        "@org_uber_go_zap//:go_default_library",
     ],
 )
 
@@ -22,5 +22,4 @@
     name = "go_default_test",
     srcs = ["supervisor_test.go"],
     embed = [":go_default_library"],
-    deps = ["@org_uber_go_zap//:go_default_library"],
 )
diff --git a/core/internal/common/supervisor/supervisor.go b/core/internal/common/supervisor/supervisor.go
index db4489e..ef8a9cd 100644
--- a/core/internal/common/supervisor/supervisor.go
+++ b/core/internal/common/supervisor/supervisor.go
@@ -22,9 +22,10 @@
 
 import (
 	"context"
+	"io"
 	"sync"
 
-	"go.uber.org/zap"
+	"git.monogon.dev/source/nexantic.git/core/pkg/logtree"
 )
 
 // A Runnable is a function that will be run in a goroutine, and supervised throughout its lifetime. It can in turn
@@ -70,14 +71,6 @@
 	SignalDone
 )
 
-// Logger returns a Zap logger that will be named after the Distinguished Name of a the runnable (ie its place in the
-// supervision tree, dot-separated).
-func Logger(ctx context.Context) *zap.Logger {
-	node, unlock := fromContext(ctx)
-	defer unlock()
-	return node.getLogger()
-}
-
 // supervisor represents and instance of the supervision system. It keeps track of a supervision tree and a request
 // channel to its internal processor goroutine.
 type supervisor struct {
@@ -86,10 +79,10 @@
 	// root is the root node of the supervision tree, named 'root'. It represents the Runnable started with the
 	// supervisor.New call.
 	root *node
-	// logger is the Zap logger used to create loggers available to runnables.
-	logger *zap.Logger
-	// ilogger is the Zap logger used for internal logging by the supervisor.
-	ilogger *zap.Logger
+	// logtree is the main logtree exposed to runnables and used internally.
+	logtree *logtree.LogTree
+	// ilogger is the internal logger logging to "supervisor" in the logtree.
+	ilogger logtree.LeveledLogger
 
 	// pReq is an interface channel to the lifecycle processor of the supervisor.
 	pReq chan *processorRequest
@@ -109,12 +102,17 @@
 	}
 )
 
+func WithExistingLogtree(lt *logtree.LogTree) SupervisorOpt {
+	return func(s *supervisor) {
+		s.logtree = lt
+	}
+}
+
 // New creates a new supervisor with its root running the given root runnable.
 // The given context can be used to cancel the entire supervision tree.
-func New(ctx context.Context, logger *zap.Logger, rootRunnable Runnable, opts ...SupervisorOpt) *supervisor {
+func New(ctx context.Context, rootRunnable Runnable, opts ...SupervisorOpt) *supervisor {
 	sup := &supervisor{
-		logger:  logger,
-		ilogger: logger.Named("supervisor"),
+		logtree: logtree.New(),
 		pReq:    make(chan *processorRequest),
 	}
 
@@ -122,6 +120,7 @@
 		o(sup)
 	}
 
+	sup.ilogger = sup.logtree.MustLeveledFor("supervisor")
 	sup.root = newNode("root", rootRunnable, sup, nil)
 
 	go sup.processor(ctx)
@@ -132,3 +131,15 @@
 
 	return sup
 }
+
+func Logger(ctx context.Context) logtree.LeveledLogger {
+	node, unlock := fromContext(ctx)
+	defer unlock()
+	return node.sup.logtree.MustLeveledFor(logtree.DN(node.dn()))
+}
+
+func RawLogger(ctx context.Context) io.Writer {
+	node, unlock := fromContext(ctx)
+	defer unlock()
+	return node.sup.logtree.MustRawFor(logtree.DN(node.dn()))
+}
diff --git a/core/internal/common/supervisor/supervisor_node.go b/core/internal/common/supervisor/supervisor_node.go
index e2af62c..a7caf82 100644
--- a/core/internal/common/supervisor/supervisor_node.go
+++ b/core/internal/common/supervisor/supervisor_node.go
@@ -23,7 +23,6 @@
 	"strings"
 
 	"github.com/cenkalti/backoff/v4"
-	"go.uber.org/zap"
 )
 
 // node is a supervision tree node. It represents the state of a Runnable within this tree, its relation to other tree
@@ -281,8 +280,3 @@
 		n.bo.Reset()
 	}
 }
-
-// getLogger creates a new logger for a given supervisor node, to be used by its runnable.
-func (n *node) getLogger() *zap.Logger {
-	return n.sup.logger.Named(n.dn())
-}
diff --git a/core/internal/common/supervisor/supervisor_processor.go b/core/internal/common/supervisor/supervisor_processor.go
index c72ef89..965a667 100644
--- a/core/internal/common/supervisor/supervisor_processor.go
+++ b/core/internal/common/supervisor/supervisor_processor.go
@@ -22,8 +22,6 @@
 	"fmt"
 	"runtime/debug"
 	"time"
-
-	"go.uber.org/zap"
 )
 
 // The processor maintains runnable goroutines - ie., when requested will start one, and then once it exists it will
@@ -76,7 +74,7 @@
 	for {
 		select {
 		case <-ctx.Done():
-			s.ilogger.Info("supervisor processor exiting...", zap.Error(ctx.Err()))
+			s.ilogger.Infof("supervisor processor exiting: %v", ctx.Err())
 			s.processKill()
 			s.ilogger.Info("supervisor exited")
 			return
@@ -213,7 +211,7 @@
 		err = fmt.Errorf("returned error when %s: %w", n.state, err)
 	}
 
-	s.ilogger.Error("Runnable died", zap.String("dn", n.dn()), zap.Error(err))
+	s.ilogger.Errorf("Runnable %s died: %v", n.dn(), err)
 	// Mark as dead.
 	n.state = nodeStateDead
 
@@ -393,7 +391,7 @@
 
 		// Prepare node for rescheduling - remove its children, reset its state to new.
 		n.reset()
-		s.ilogger.Info("rescheduling supervised node", zap.String("dn", dn), zap.Duration("backoff", bo))
+		s.ilogger.Infof("rescheduling supervised node %s with backoff %s", dn, bo.String())
 
 		// Reschedule node runnable to run after backoff.
 		go func(n *node, bo time.Duration) {
diff --git a/core/internal/common/supervisor/supervisor_test.go b/core/internal/common/supervisor/supervisor_test.go
index 9a190c9..9c7bdb7 100644
--- a/core/internal/common/supervisor/supervisor_test.go
+++ b/core/internal/common/supervisor/supervisor_test.go
@@ -21,8 +21,6 @@
 	"fmt"
 	"testing"
 	"time"
-
-	"go.uber.org/zap"
 )
 
 func runnableBecomesHealthy(healthy, done chan struct{}) Runnable {
@@ -182,10 +180,9 @@
 	h2 := make(chan struct{})
 	d2 := make(chan struct{})
 
-	log, _ := zap.NewDevelopment()
 	ctx, ctxC := context.WithCancel(context.Background())
 	defer ctxC()
-	s := New(ctx, log, func(ctx context.Context) error {
+	s := New(ctx, func(ctx context.Context) error {
 		err := RunGroup(ctx, map[string]Runnable{
 			"one": runnableBecomesHealthy(h1, d1),
 			"two": runnableBecomesHealthy(h2, d2),
@@ -217,10 +214,9 @@
 	d1 := make(chan struct{})
 	two := newRC()
 
-	log, _ := zap.NewDevelopment()
 	ctx, ctxC := context.WithTimeout(context.Background(), 10*time.Second)
 	defer ctxC()
-	s := New(ctx, log, func(ctx context.Context) error {
+	s := New(ctx, func(ctx context.Context) error {
 		err := RunGroup(ctx, map[string]Runnable{
 			"one": runnableBecomesHealthy(h1, d1),
 			"two": two.runnable(),
@@ -266,11 +262,9 @@
 	d1 := make(chan struct{})
 	two := newRC()
 
-	log, _ := zap.NewDevelopment()
-
 	ctx, ctxC := context.WithTimeout(context.Background(), 10*time.Second)
 	defer ctxC()
-	s := New(ctx, log, func(ctx context.Context) error {
+	s := New(ctx, func(ctx context.Context) error {
 		err := RunGroup(ctx, map[string]Runnable{
 			"one": runnableSpawnsMore(h1, d1, 5),
 			"two": two.runnable(),
@@ -315,10 +309,9 @@
 	d1 := make(chan struct{})
 	two := newRC()
 
-	log, _ := zap.NewDevelopment()
 	ctx, ctxC := context.WithCancel(context.Background())
 	defer ctxC()
-	s := New(ctx, log, func(ctx context.Context) error {
+	s := New(ctx, func(ctx context.Context) error {
 		err := RunGroup(ctx, map[string]Runnable{
 			"one": runnableBecomesHealthy(h1, d1),
 			"two": two.runnable(),
@@ -359,10 +352,9 @@
 }
 
 func TestMultipleLevelFailure(t *testing.T) {
-	log, _ := zap.NewDevelopment()
 	ctx, ctxC := context.WithCancel(context.Background())
 	defer ctxC()
-	New(ctx, log, func(ctx context.Context) error {
+	New(ctx, func(ctx context.Context) error {
 		err := RunGroup(ctx, map[string]Runnable{
 			"one": runnableSpawnsMore(nil, nil, 4),
 			"two": runnableSpawnsMore(nil, nil, 4),
@@ -379,11 +371,10 @@
 func TestBackoff(t *testing.T) {
 	one := newRC()
 
-	log, _ := zap.NewDevelopment()
 	ctx, ctxC := context.WithTimeout(context.Background(), 20*time.Second)
 	defer ctxC()
 
-	s := New(ctx, log, func(ctx context.Context) error {
+	s := New(ctx, func(ctx context.Context) error {
 		if err := Run(ctx, "one", one.runnable()); err != nil {
 			return err
 		}
@@ -485,10 +476,9 @@
 		}
 	}
 
-	log, _ := zap.NewDevelopment()
 	ctx, ctxC := context.WithCancel(context.Background())
 	defer ctxC()
-	New(ctx, log, func(ctx context.Context) error {
+	New(ctx, func(ctx context.Context) error {
 		RunGroup(ctx, map[string]Runnable{
 			"one":        one,
 			"oneSibling": oneSibling.runnable(),
@@ -538,12 +528,10 @@
 		return nil
 	}
 
-	log, _ := zap.NewDevelopment()
-
 	// Start a supervision tree with a root runnable.
 	ctx, ctxC := context.WithCancel(context.Background())
 	defer ctxC()
-	New(ctx, log, func(ctx context.Context) error {
+	New(ctx, func(ctx context.Context) error {
 		err := Run(ctx, "child", child)
 		if err != nil {
 			return fmt.Errorf("could not run 'child': %w", err)