osbase/logtree.LeveledLogger -> go/logging.Leveled

This factors out the common leveled logger interface out of the logtree.
We want to use the same interface outside of logtree/supervisor usage
within the resolver code, which will be exposed to clients.

Change-Id: I299e76d91e8cefddf8f36f1e58432418c4694df2
Reviewed-on: https://review.monogon.dev/c/monogon/+/3411
Reviewed-by: Tim Windelschmidt <tim@monogon.tech>
Tested-by: Jenkins CI
diff --git a/metropolis/node/core/BUILD.bazel b/metropolis/node/core/BUILD.bazel
index b511bb9..667f7f3 100644
--- a/metropolis/node/core/BUILD.bazel
+++ b/metropolis/node/core/BUILD.bazel
@@ -23,6 +23,7 @@
     importpath = "source.monogon.dev/metropolis/node/core",
     visibility = ["//visibility:private"],
     deps = [
+        "//go/logging",
         "//metropolis/node",
         "//metropolis/node/core/cluster",
         "//metropolis/node/core/devmgr",
diff --git a/metropolis/node/core/consensus/BUILD.bazel b/metropolis/node/core/consensus/BUILD.bazel
index b68c7f9..ac048d6 100644
--- a/metropolis/node/core/consensus/BUILD.bazel
+++ b/metropolis/node/core/consensus/BUILD.bazel
@@ -12,6 +12,7 @@
     importpath = "source.monogon.dev/metropolis/node/core/consensus",
     visibility = ["//:__subpackages__"],
     deps = [
+        "//go/logging",
         "//metropolis/node",
         "//metropolis/node/core/consensus/client",
         "//metropolis/node/core/identity",
@@ -44,6 +45,7 @@
         "block-network",
     ],
     deps = [
+        "//go/logging",
         "//metropolis/node/core/localstorage",
         "//metropolis/node/core/localstorage/declarative",
         "//metropolis/test/util",
diff --git a/metropolis/node/core/consensus/logparser.go b/metropolis/node/core/consensus/logparser.go
index b403423..f825431 100644
--- a/metropolis/node/core/consensus/logparser.go
+++ b/metropolis/node/core/consensus/logparser.go
@@ -8,6 +8,7 @@
 	"strings"
 	"time"
 
+	"source.monogon.dev/go/logging"
 	"source.monogon.dev/osbase/logbuffer"
 	"source.monogon.dev/osbase/logtree"
 	"source.monogon.dev/osbase/logtree/unraw"
@@ -80,13 +81,13 @@
 	// Convert zap level into logtree severity.
 	switch e.Level {
 	case "info":
-		out.Severity = logtree.INFO
+		out.Severity = logging.INFO
 	case "warn":
-		out.Severity = logtree.WARNING
+		out.Severity = logging.WARNING
 	case "error":
-		out.Severity = logtree.ERROR
+		out.Severity = logging.ERROR
 	case "fatal", "panic", "dpanic":
-		out.Severity = logtree.FATAL
+		out.Severity = logging.FATAL
 	}
 
 	// Sort extra keys alphabetically.
diff --git a/metropolis/node/core/consensus/logparser_test.go b/metropolis/node/core/consensus/logparser_test.go
index cfe6fea..101211c 100644
--- a/metropolis/node/core/consensus/logparser_test.go
+++ b/metropolis/node/core/consensus/logparser_test.go
@@ -6,6 +6,7 @@
 
 	"github.com/google/go-cmp/cmp"
 
+	"source.monogon.dev/go/logging"
 	"source.monogon.dev/osbase/logbuffer"
 	"source.monogon.dev/osbase/logtree"
 )
@@ -35,7 +36,7 @@
 			&logtree.ExternalLeveledPayload{
 				Message:   `configuring peer listeners, listen-peer-urls: ["https://[::]:7834"]`,
 				Timestamp: timeParse("2021-07-06T17:18:24.368Z"),
-				Severity:  logtree.INFO,
+				Severity:  logging.INFO,
 				File:      "etcd.go",
 				Line:      117,
 			},
@@ -46,7 +47,7 @@
 			&logtree.ExternalLeveledPayload{
 				Message:   `added member, added-peer-id: "9642132f5d0d99e2", added-peer-peer-urls: ["https://metropolis-eb8d68cfb52711ad04c339abdeea74ed:7834"], cluster-id: "137c8e19524788c1", local-member-id: "9642132f5d0d99e2"`,
 				Timestamp: timeParse("2021-07-06T17:21:49.462Z"),
-				Severity:  logtree.INFO,
+				Severity:  logging.INFO,
 				File:      "cluster.go",
 				Line:      392,
 			},
diff --git a/metropolis/node/core/main.go b/metropolis/node/core/main.go
index eba6773..e675f87 100644
--- a/metropolis/node/core/main.go
+++ b/metropolis/node/core/main.go
@@ -25,6 +25,7 @@
 
 	"golang.org/x/sys/unix"
 
+	"source.monogon.dev/go/logging"
 	"source.monogon.dev/metropolis/node/core/cluster"
 	"source.monogon.dev/metropolis/node/core/devmgr"
 	"source.monogon.dev/metropolis/node/core/localstorage"
@@ -302,23 +303,23 @@
 	}
 	s := string(p.DN)
 	if strings.HasPrefix(s, "root.role.controlplane.launcher.consensus.etcd") {
-		return p.Leveled.Severity().AtLeast(logtree.WARNING)
+		return p.Leveled.Severity().AtLeast(logging.WARNING)
 	}
 	// TODO(q3k): turn off RPC traces instead
 	if strings.HasPrefix(s, "root.role.controlplane.launcher.curator.listener.rpc") {
 		return false
 	}
 	if strings.HasPrefix(s, "root.role.kubernetes.run.kubernetes.networked.kubelet") {
-		return p.Leveled.Severity().AtLeast(logtree.WARNING)
+		return p.Leveled.Severity().AtLeast(logging.WARNING)
 	}
 	if strings.HasPrefix(s, "root.role.kubernetes.run.kubernetes.networked.apiserver") {
-		return p.Leveled.Severity().AtLeast(logtree.WARNING)
+		return p.Leveled.Severity().AtLeast(logging.WARNING)
 	}
 	if strings.HasPrefix(s, "root.role.kubernetes.run.kubernetes.controller-manager") {
-		return p.Leveled.Severity().AtLeast(logtree.WARNING)
+		return p.Leveled.Severity().AtLeast(logging.WARNING)
 	}
 	if strings.HasPrefix(s, "root.role.kubernetes.run.kubernetes.scheduler") {
-		return p.Leveled.Severity().AtLeast(logtree.WARNING)
+		return p.Leveled.Severity().AtLeast(logging.WARNING)
 	}
 	if strings.HasPrefix(s, "root.kernel") {
 		// Linux writes high-severity logs directly to the console anyways and
@@ -326,7 +327,7 @@
 		return false
 	}
 	if strings.HasPrefix(s, "supervisor") {
-		return p.Leveled.Severity().AtLeast(logtree.WARNING)
+		return p.Leveled.Severity().AtLeast(logging.WARNING)
 	}
 	return true
 }
diff --git a/metropolis/node/core/network/BUILD.bazel b/metropolis/node/core/network/BUILD.bazel
index 8ef2e6c..6809c58 100644
--- a/metropolis/node/core/network/BUILD.bazel
+++ b/metropolis/node/core/network/BUILD.bazel
@@ -12,10 +12,10 @@
     visibility = ["//:__subpackages__"],
     deps = [
         "//go/algorithm/toposort",
+        "//go/logging",
         "//metropolis/node/core/network/dhcp4c",
         "//metropolis/node/core/network/dhcp4c/callback",
         "//osbase/event/memory",
-        "//osbase/logtree",
         "//osbase/net/dns",
         "//osbase/net/dns/forward",
         "//osbase/net/proto",
diff --git a/metropolis/node/core/network/quirks.go b/metropolis/node/core/network/quirks.go
index 6a3f5cc..547d91e 100644
--- a/metropolis/node/core/network/quirks.go
+++ b/metropolis/node/core/network/quirks.go
@@ -9,12 +9,12 @@
 	"github.com/vishvananda/netlink"
 	"golang.org/x/sys/unix"
 
-	"source.monogon.dev/osbase/logtree"
+	"source.monogon.dev/go/logging"
 )
 
 // applyQuirks applies settings to drivers and/or hardware to make it work
 // better (i.e. with less crashes or faster).
-func applyQuirks(l logtree.LeveledLogger) error {
+func applyQuirks(l logging.Leveled) error {
 	ethtoolFd, err := unix.Socket(unix.AF_INET, unix.SOCK_DGRAM, unix.IPPROTO_IP)
 	if err != nil {
 		return fmt.Errorf("while creating IP socket for ethtool: %w", err)
diff --git a/metropolis/node/core/network/static.go b/metropolis/node/core/network/static.go
index 86c45f6..fdd00a8 100644
--- a/metropolis/node/core/network/static.go
+++ b/metropolis/node/core/network/static.go
@@ -16,9 +16,9 @@
 	"golang.org/x/sys/unix"
 
 	"source.monogon.dev/go/algorithm/toposort"
+	"source.monogon.dev/go/logging"
 	"source.monogon.dev/metropolis/node/core/network/dhcp4c"
 	dhcpcb "source.monogon.dev/metropolis/node/core/network/dhcp4c/callback"
-	"source.monogon.dev/osbase/logtree"
 	"source.monogon.dev/osbase/supervisor"
 	"source.monogon.dev/osbase/sysctl"
 
@@ -272,7 +272,7 @@
 	return hostDevices, nil
 }
 
-func deviceIfaceFromSpec(it *netpb.Interface_Device, hostDevices []deviceIfData, l logtree.LeveledLogger) (*netlink.Device, error) {
+func deviceIfaceFromSpec(it *netpb.Interface_Device, hostDevices []deviceIfData, l logging.Leveled) (*netlink.Device, error) {
 	var matchedDevices []*netlink.Device
 	var err error
 	var parsedHWAddr net.HardwareAddr
diff --git a/metropolis/node/core/rpc/BUILD.bazel b/metropolis/node/core/rpc/BUILD.bazel
index e80ded4..fcc68fa 100644
--- a/metropolis/node/core/rpc/BUILD.bazel
+++ b/metropolis/node/core/rpc/BUILD.bazel
@@ -13,10 +13,10 @@
     importpath = "source.monogon.dev/metropolis/node/core/rpc",
     visibility = ["//visibility:public"],
     deps = [
+        "//go/logging",
         "//metropolis/node/core/identity",
         "//metropolis/proto/api",
         "//metropolis/proto/ext",
-        "//osbase/logtree",
         "@org_golang_google_grpc//:grpc",
         "@org_golang_google_grpc//codes",
         "@org_golang_google_grpc//credentials",
diff --git a/metropolis/node/core/rpc/server_authentication.go b/metropolis/node/core/rpc/server_authentication.go
index c7d6e91..eed7dba 100644
--- a/metropolis/node/core/rpc/server_authentication.go
+++ b/metropolis/node/core/rpc/server_authentication.go
@@ -12,8 +12,8 @@
 	"google.golang.org/grpc/peer"
 	"google.golang.org/grpc/status"
 
+	"source.monogon.dev/go/logging"
 	"source.monogon.dev/metropolis/node/core/identity"
-	"source.monogon.dev/osbase/logtree"
 )
 
 // ServerSecurity are the security options of a RPC server that will run
@@ -37,7 +37,7 @@
 // metropolis.proto.ext.authorization options and authenticate/authorize
 // incoming connections. It also runs the gRPC server with the correct TLS
 // settings for authenticating itself to callers.
-func (s *ServerSecurity) GRPCOptions(logger logtree.LeveledLogger) []grpc.ServerOption {
+func (s *ServerSecurity) GRPCOptions(logger logging.Leveled) []grpc.ServerOption {
 	externalCreds := credentials.NewTLS(&tls.Config{
 		Certificates: []tls.Certificate{s.NodeCredentials.TLSCredentials()},
 		ClientAuth:   tls.RequestClientCert,
@@ -53,7 +53,7 @@
 // streamInterceptor returns a gRPC StreamInterceptor interface for use with
 // grpc.NewServer. It's applied to gRPC servers started within Metropolis,
 // notably to the Curator.
-func (s *ServerSecurity) streamInterceptor(logger logtree.LeveledLogger) grpc.StreamServerInterceptor {
+func (s *ServerSecurity) streamInterceptor(logger logging.Leveled) grpc.StreamServerInterceptor {
 	return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
 		var span *logtreeSpan
 		// HACK: Do not log any log retrieval methods into the log, otherwise logs blow up
@@ -87,7 +87,7 @@
 // unaryInterceptor returns a gRPC UnaryInterceptor interface for use with
 // grpc.NewServer. It's applied to gRPC servers started within Metropolis,
 // notably to the Curator.
-func (s *ServerSecurity) unaryInterceptor(logger logtree.LeveledLogger) grpc.UnaryServerInterceptor {
+func (s *ServerSecurity) unaryInterceptor(logger logging.Leveled) grpc.UnaryServerInterceptor {
 	return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
 		// Inject span if we have a logger.
 		if logger != nil {
diff --git a/metropolis/node/core/rpc/trace.go b/metropolis/node/core/rpc/trace.go
index a686c06..f27a311 100644
--- a/metropolis/node/core/rpc/trace.go
+++ b/metropolis/node/core/rpc/trace.go
@@ -10,7 +10,7 @@
 	"google.golang.org/protobuf/encoding/prototext"
 	"google.golang.org/protobuf/proto"
 
-	"source.monogon.dev/osbase/logtree"
+	"source.monogon.dev/go/logging"
 )
 
 // Span implements a compatible subset of
@@ -64,14 +64,14 @@
 	// logger is the logtree LeveledLogger backing this span. All Events added into
 	// the Span will go straight into that logger. If the logger is nil, all events
 	// will be dropped instead.
-	logger logtree.LeveledLogger
+	logger logging.Leveled
 	// uid is the span ID of this logtreeSpan. Currently this is a monotonic counter
 	// based on the current nanosecond epoch, but this might change in the future.
 	// This field is ignored if logger is nil.
 	uid uint64
 }
 
-func newLogtreeSpan(l logtree.LeveledLogger) *logtreeSpan {
+func newLogtreeSpan(l logging.Leveled) *logtreeSpan {
 	uid := uint64(time.Now().UnixNano())
 	return &logtreeSpan{
 		logger: l,
diff --git a/metropolis/node/core/update/BUILD.bazel b/metropolis/node/core/update/BUILD.bazel
index f60ba40..6b12a94 100644
--- a/metropolis/node/core/update/BUILD.bazel
+++ b/metropolis/node/core/update/BUILD.bazel
@@ -9,13 +9,13 @@
     importpath = "source.monogon.dev/metropolis/node/core/update",
     visibility = ["//visibility:public"],
     deps = [
+        "//go/logging",
         "//metropolis/node/core/abloader/spec",
         "//osbase/blockdev",
         "//osbase/build/mkimage/osimage",
         "//osbase/efivarfs",
         "//osbase/gpt",
         "//osbase/kexec",
-        "//osbase/logtree",
         "@com_github_cenkalti_backoff_v4//:backoff",
         "@org_golang_google_grpc//codes",
         "@org_golang_google_grpc//status",
diff --git a/metropolis/node/core/update/update.go b/metropolis/node/core/update/update.go
index 7c9e1c3..2e30d2a 100644
--- a/metropolis/node/core/update/update.go
+++ b/metropolis/node/core/update/update.go
@@ -23,13 +23,13 @@
 	"google.golang.org/grpc/status"
 	"google.golang.org/protobuf/proto"
 
+	"source.monogon.dev/go/logging"
 	abloaderpb "source.monogon.dev/metropolis/node/core/abloader/spec"
 	"source.monogon.dev/osbase/blockdev"
 	"source.monogon.dev/osbase/build/mkimage/osimage"
 	"source.monogon.dev/osbase/efivarfs"
 	"source.monogon.dev/osbase/gpt"
 	"source.monogon.dev/osbase/kexec"
-	"source.monogon.dev/osbase/logtree"
 )
 
 // Service contains data and functionality to perform A/B updates on a
@@ -43,7 +43,7 @@
 	ESPPartNumber uint32
 
 	// Logger service for the update service.
-	Logger logtree.LeveledLogger
+	Logger logging.Leveled
 }
 
 type Slot int
diff --git a/metropolis/node/kubernetes/BUILD.bazel b/metropolis/node/kubernetes/BUILD.bazel
index f1af467..d4a36dc 100644
--- a/metropolis/node/kubernetes/BUILD.bazel
+++ b/metropolis/node/kubernetes/BUILD.bazel
@@ -16,6 +16,7 @@
     importpath = "source.monogon.dev/metropolis/node/kubernetes",
     visibility = ["//metropolis/node:__subpackages__"],
     deps = [
+        "//go/logging",
         "//go/net/tinylb",
         "//metropolis/node",
         "//metropolis/node/core/clusternet",
@@ -37,7 +38,6 @@
         "//osbase/event/memory",
         "//osbase/fileargs",
         "//osbase/fsquota",
-        "//osbase/logtree",
         "//osbase/loop",
         "//osbase/net/dns/kubernetes",
         "//osbase/supervisor",
diff --git a/metropolis/node/kubernetes/clusternet/BUILD.bazel b/metropolis/node/kubernetes/clusternet/BUILD.bazel
index 6b4d744..79bedbe 100644
--- a/metropolis/node/kubernetes/clusternet/BUILD.bazel
+++ b/metropolis/node/kubernetes/clusternet/BUILD.bazel
@@ -6,9 +6,9 @@
     importpath = "source.monogon.dev/metropolis/node/kubernetes/clusternet",
     visibility = ["//metropolis/node/kubernetes:__subpackages__"],
     deps = [
+        "//go/logging",
         "//metropolis/node/core/clusternet",
         "//osbase/event",
-        "//osbase/logtree",
         "//osbase/supervisor",
         "@io_k8s_api//core/v1:core",
         "@io_k8s_apimachinery//pkg/fields",
diff --git a/metropolis/node/kubernetes/clusternet/clusternet.go b/metropolis/node/kubernetes/clusternet/clusternet.go
index 28e268d..30c15a1 100644
--- a/metropolis/node/kubernetes/clusternet/clusternet.go
+++ b/metropolis/node/kubernetes/clusternet/clusternet.go
@@ -41,9 +41,9 @@
 	"k8s.io/client-go/kubernetes"
 	"k8s.io/client-go/tools/cache"
 
+	"source.monogon.dev/go/logging"
 	oclusternet "source.monogon.dev/metropolis/node/core/clusternet"
 	"source.monogon.dev/osbase/event"
-	"source.monogon.dev/osbase/logtree"
 	"source.monogon.dev/osbase/supervisor"
 )
 
@@ -52,7 +52,7 @@
 	Kubernetes kubernetes.Interface
 	Prefixes   event.Value[*oclusternet.Prefixes]
 
-	logger logtree.LeveledLogger
+	logger logging.Leveled
 }
 
 // ensureNode is called any time the node that this Service is running on gets
diff --git a/metropolis/node/kubernetes/csi.go b/metropolis/node/kubernetes/csi.go
index dfbd48c..3236bba 100644
--- a/metropolis/node/kubernetes/csi.go
+++ b/metropolis/node/kubernetes/csi.go
@@ -33,9 +33,9 @@
 	"google.golang.org/protobuf/types/known/wrapperspb"
 	pluginregistration "k8s.io/kubelet/pkg/apis/pluginregistration/v1"
 
+	"source.monogon.dev/go/logging"
 	"source.monogon.dev/metropolis/node/core/localstorage"
 	"source.monogon.dev/osbase/fsquota"
-	"source.monogon.dev/osbase/logtree"
 	"source.monogon.dev/osbase/loop"
 	"source.monogon.dev/osbase/supervisor"
 )
@@ -51,7 +51,7 @@
 	KubeletDirectory *localstorage.DataKubernetesKubeletDirectory
 	VolumesDirectory *localstorage.DataVolumesDirectory
 
-	logger logtree.LeveledLogger
+	logger logging.Leveled
 }
 
 func (s *csiPluginServer) Run(ctx context.Context) error {
diff --git a/metropolis/node/kubernetes/plugins/kvmdevice/BUILD.bazel b/metropolis/node/kubernetes/plugins/kvmdevice/BUILD.bazel
index d6afb23..afb236a 100644
--- a/metropolis/node/kubernetes/plugins/kvmdevice/BUILD.bazel
+++ b/metropolis/node/kubernetes/plugins/kvmdevice/BUILD.bazel
@@ -6,8 +6,8 @@
     importpath = "source.monogon.dev/metropolis/node/kubernetes/plugins/kvmdevice",
     visibility = ["//visibility:public"],
     deps = [
+        "//go/logging",
         "//metropolis/node/core/localstorage",
-        "//osbase/logtree",
         "//osbase/supervisor",
         "@io_k8s_api//core/v1:core",
         "@io_k8s_kubelet//pkg/apis/deviceplugin/v1beta1",
diff --git a/metropolis/node/kubernetes/plugins/kvmdevice/kvmdevice.go b/metropolis/node/kubernetes/plugins/kvmdevice/kvmdevice.go
index f285c47..4d3f4a1 100644
--- a/metropolis/node/kubernetes/plugins/kvmdevice/kvmdevice.go
+++ b/metropolis/node/kubernetes/plugins/kvmdevice/kvmdevice.go
@@ -39,8 +39,8 @@
 	deviceplugin "k8s.io/kubelet/pkg/apis/deviceplugin/v1beta1"
 	pluginregistration "k8s.io/kubelet/pkg/apis/pluginregistration/v1"
 
+	"source.monogon.dev/go/logging"
 	"source.monogon.dev/metropolis/node/core/localstorage"
-	"source.monogon.dev/osbase/logtree"
 	"source.monogon.dev/osbase/supervisor"
 )
 
@@ -51,7 +51,7 @@
 	*deviceplugin.UnimplementedDevicePluginServer
 	KubeletDirectory *localstorage.DataKubernetesKubeletDirectory
 
-	logger logtree.LeveledLogger
+	logger logging.Leveled
 }
 
 func (k *Plugin) GetInfo(context.Context, *pluginregistration.InfoRequest) (*pluginregistration.PluginInfo, error) {
diff --git a/metropolis/node/kubernetes/provisioner.go b/metropolis/node/kubernetes/provisioner.go
index 46fd908..aacb949 100644
--- a/metropolis/node/kubernetes/provisioner.go
+++ b/metropolis/node/kubernetes/provisioner.go
@@ -39,9 +39,9 @@
 	ref "k8s.io/client-go/tools/reference"
 	"k8s.io/client-go/util/workqueue"
 
+	"source.monogon.dev/go/logging"
 	"source.monogon.dev/metropolis/node/core/localstorage"
 	"source.monogon.dev/osbase/fsquota"
-	"source.monogon.dev/osbase/logtree"
 	"source.monogon.dev/osbase/supervisor"
 )
 
@@ -72,7 +72,7 @@
 	pvcInformer          coreinformers.PersistentVolumeClaimInformer
 	pvInformer           coreinformers.PersistentVolumeInformer
 	storageClassInformer storageinformers.StorageClassInformer
-	logger               logtree.LeveledLogger
+	logger               logging.Leveled
 }
 
 // runCSIProvisioner runs the main provisioning machinery. It consists of a