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/cloud/agent/BUILD.bazel b/cloud/agent/BUILD.bazel
index db3ee51..7e7614d 100644
--- a/cloud/agent/BUILD.bazel
+++ b/cloud/agent/BUILD.bazel
@@ -15,13 +15,13 @@
deps = [
"//cloud/agent/api",
"//cloud/bmaas/server/api",
+ "//go/logging",
"//metropolis/node/core/devmgr",
"//metropolis/node/core/network",
"//osbase/blockdev",
"//osbase/bringup",
"//osbase/build/mkimage/osimage",
"//osbase/efivarfs",
- "//osbase/logtree",
"//osbase/net/proto",
"//osbase/nvme",
"//osbase/pki",
diff --git a/cloud/agent/install.go b/cloud/agent/install.go
index 29641bd..932cff8 100644
--- a/cloud/agent/install.go
+++ b/cloud/agent/install.go
@@ -15,10 +15,10 @@
"google.golang.org/protobuf/proto"
bpb "source.monogon.dev/cloud/bmaas/server/api"
+ "source.monogon.dev/go/logging"
"source.monogon.dev/osbase/blockdev"
"source.monogon.dev/osbase/build/mkimage/osimage"
"source.monogon.dev/osbase/efivarfs"
- "source.monogon.dev/osbase/logtree"
npb "source.monogon.dev/osbase/net/proto"
)
@@ -42,7 +42,7 @@
// install dispatches OSInstallationRequests to the appropriate installer
// method
-func install(req *bpb.OSInstallationRequest, netConfig *npb.Net, l logtree.LeveledLogger) error {
+func install(req *bpb.OSInstallationRequest, netConfig *npb.Net, l logging.Leveled) error {
switch reqT := req.Type.(type) {
case *bpb.OSInstallationRequest_Metropolis:
return installMetropolis(reqT.Metropolis, netConfig, l)
@@ -51,7 +51,7 @@
}
}
-func installMetropolis(req *bpb.MetropolisInstallationRequest, netConfig *npb.Net, l logtree.LeveledLogger) error {
+func installMetropolis(req *bpb.MetropolisInstallationRequest, netConfig *npb.Net, l logging.Leveled) error {
// Validate we are running via EFI.
if _, err := os.Stat("/sys/firmware/efi"); os.IsNotExist(err) {
//nolint:ST1005
diff --git a/go/logging/BUILD.bazel b/go/logging/BUILD.bazel
new file mode 100644
index 0000000..4a5feae
--- /dev/null
+++ b/go/logging/BUILD.bazel
@@ -0,0 +1,8 @@
+load("@io_bazel_rules_go//go:def.bzl", "go_library")
+
+go_library(
+ name = "logging",
+ srcs = ["leveled.go"],
+ importpath = "source.monogon.dev/go/logging",
+ visibility = ["//visibility:public"],
+)
diff --git a/go/logging/leveled.go b/go/logging/leveled.go
new file mode 100644
index 0000000..a32b62d
--- /dev/null
+++ b/go/logging/leveled.go
@@ -0,0 +1,123 @@
+package logging
+
+// Leveled is a generic interface for glog-style logging. There are four
+// hardcoded log severities, in increasing order: INFO, WARNING, ERROR, FATAL.
+// Logging at a certain severity level logs not only to consumers expecting data
+// at that severity level, but also all lower severity levels. For example, an
+// ERROR log will also be passed to consumers looking at INFO or WARNING logs.
+type Leveled interface {
+ // Info logs at the INFO severity. Arguments are handled in the manner of
+ // fmt.Print, a terminating newline is added if missing.
+ Info(args ...any)
+ // Infof logs at the INFO severity. Arguments are handled in the manner of
+ // fmt.Printf, a terminating newline is added if missing.
+ Infof(format string, args ...any)
+
+ // Warning logs at the WARNING severity. Arguments are handled in the manner of
+ // fmt.Print, a terminating newline is added if missing.
+ Warning(args ...any)
+ // Warningf logs at the WARNING severity. Arguments are handled in the manner of
+ // fmt.Printf, a terminating newline is added if missing.
+ Warningf(format string, args ...any)
+
+ // Error logs at the ERROR severity. Arguments are handled in the manner of
+ // fmt.Print, a terminating newline is added if missing.
+ Error(args ...any)
+ // Errorf logs at the ERROR severity. Arguments are handled in the manner of
+ // fmt.Printf, a terminating newline is added if missing.
+ Errorf(format string, args ...any)
+
+ // Fatal logs at the FATAL severity and aborts the current program. Arguments are
+ // handled in the manner of fmt.Print, a terminating newline is added if missing.
+ Fatal(args ...any)
+ // Fatalf logs at the FATAL severity and aborts the current program. Arguments are
+ // handled in the manner of fmt.Printf, a terminating newline is added if missing.
+ Fatalf(format string, args ...any)
+
+ // V returns a VerboseLeveledLogger at a given verbosity level. These verbosity
+ // levels can be dynamically set and unset on a package-granular level by consumers
+ // of the LeveledLogger logs. The returned value represents whether logging at the
+ // given verbosity level was active at that time, and as such should not be a long-
+ // lived object in programs. This construct is further refered to as 'V-logs'.
+ V(level VerbosityLevel) VerboseLeveled
+
+ // WithAddedStackDepth returns the same LeveledLogger, but adjusted with an
+ // additional 'extra stack depth' which will be used to skip a given number of
+ // stack/call frames when determining the location where the error originated.
+ // For example, WithStackDepth(1) will return a logger that will skip one
+ // stack/call frame. Then, with function foo() calling function helper() which
+ // in turns call l.Infof(), the log line will be emitted with the call site of
+ // helper() within foo(), instead of the default behaviour of logging the
+ // call site of Infof() within helper().
+ //
+ // This is useful for functions which somehow wrap loggers in helper functions,
+ // for example to expose a slightly different API.
+ WithAddedStackDepth(depth int) Leveled
+}
+
+// VerbosityLevel is a verbosity level defined for V-logs. This can be changed
+// programmatically per Go package. When logging at a given VerbosityLevel V, the
+// current level must be equal or higher to V for the logs to be recorded.
+// Conversely, enabling a V-logging at a VerbosityLevel V also enables all logging
+// at lower levels [Int32Min .. (V-1)].
+type VerbosityLevel int32
+
+type VerboseLeveled interface {
+ // Enabled returns if this level was enabled. If not enabled, all logging into this
+ // logger will be discarded immediately. Thus, Enabled() can be used to check the
+ // verbosity level before performing any logging:
+ // if l.V(3).Enabled() { l.Info("V3 is enabled") }
+ // or, in simple cases, the convenience function .Info can be used:
+ // l.V(3).Info("V3 is enabled")
+ // The second form is shorter and more convenient, but more expensive, as its
+ // arguments are always evaluated.
+ Enabled() bool
+ // Info is the equivalent of a LeveledLogger's Info call, guarded by whether this
+ // VerboseLeveledLogger is enabled.
+ Info(args ...any)
+ // Infof is the equivalent of a LeveledLogger's Infof call, guarded by whether this
+ // VerboseLeveledLogger is enabled.
+ Infof(format string, args ...any)
+}
+
+// Severity is one of the severities as described in LeveledLogger.
+type Severity string
+
+const (
+ INFO Severity = "I"
+ WARNING Severity = "W"
+ ERROR Severity = "E"
+ FATAL Severity = "F"
+)
+
+var (
+ // SeverityAtLeast maps a given severity to a list of severities that at that
+ // severity or higher. In other words, SeverityAtLeast[X] returns a list of
+ // severities that might be seen in a log at severity X.
+ SeverityAtLeast = map[Severity][]Severity{
+ INFO: {INFO, WARNING, ERROR, FATAL},
+ WARNING: {WARNING, ERROR, FATAL},
+ ERROR: {ERROR, FATAL},
+ FATAL: {FATAL},
+ }
+)
+
+func (s Severity) AtLeast(other Severity) bool {
+ for _, el := range SeverityAtLeast[other] {
+ if el == s {
+ return true
+ }
+ }
+ return false
+}
+
+// Valid returns whether true if this severity is one of the known levels
+// (INFO, WARNING, ERROR or FATAL), false otherwise.
+func (s Severity) Valid() bool {
+ switch s {
+ case INFO, WARNING, ERROR, FATAL:
+ return true
+ default:
+ return false
+ }
+}
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
diff --git a/osbase/logtree/BUILD.bazel b/osbase/logtree/BUILD.bazel
index 7c13aeb..60e8743 100644
--- a/osbase/logtree/BUILD.bazel
+++ b/osbase/logtree/BUILD.bazel
@@ -23,6 +23,7 @@
importpath = "source.monogon.dev/osbase/logtree",
visibility = ["//visibility:public"],
deps = [
+ "//go/logging",
"//osbase/logbuffer",
"//osbase/logtree/proto",
"@com_github_mitchellh_go_wordwrap//:go-wordwrap",
@@ -52,6 +53,7 @@
],
embed = [":logtree"],
deps = [
+ "//go/logging",
"@com_github_google_go_cmp//cmp",
"@org_uber_go_zap//:zap",
],
diff --git a/osbase/logtree/grpc.go b/osbase/logtree/grpc.go
index 3b2594d..7e17c56 100644
--- a/osbase/logtree/grpc.go
+++ b/osbase/logtree/grpc.go
@@ -1,9 +1,13 @@
package logtree
-import "google.golang.org/grpc/grpclog"
+import (
+ "google.golang.org/grpc/grpclog"
+
+ "source.monogon.dev/go/logging"
+)
// GRPCify turns a LeveledLogger into a go-grpc compatible logger.
-func GRPCify(logger LeveledLogger) grpclog.LoggerV2 {
+func GRPCify(logger logging.Leveled) grpclog.LoggerV2 {
lp, ok := logger.(*leveledPublisher)
if !ok {
// Fail fast, as this is a programming error.
@@ -71,5 +75,5 @@
}
func (g *leveledGRPCV2) V(l int) bool {
- return g.lp.V(VerbosityLevel(l)).Enabled()
+ return g.lp.V(logging.VerbosityLevel(l)).Enabled()
}
diff --git a/osbase/logtree/journal.go b/osbase/logtree/journal.go
index 412c042..d0e8663 100644
--- a/osbase/logtree/journal.go
+++ b/osbase/logtree/journal.go
@@ -21,6 +21,8 @@
"sort"
"strings"
"sync"
+
+ "source.monogon.dev/go/logging"
)
// DN is the Distinguished Name, a dot-delimited path used to address loggers
@@ -166,7 +168,7 @@
// filterSeverity returns a filter that accepts log entries at a given severity
// level or above. See the Severity type for more information about severity
// levels.
-func filterSeverity(atLeast Severity) filter {
+func filterSeverity(atLeast logging.Severity) filter {
return func(e *entry) bool {
return e.leveled != nil && e.leveled.severity.AtLeast(atLeast)
}
diff --git a/osbase/logtree/journal_test.go b/osbase/logtree/journal_test.go
index e9fc3b4..d295732 100644
--- a/osbase/logtree/journal_test.go
+++ b/osbase/logtree/journal_test.go
@@ -21,13 +21,15 @@
"strings"
"testing"
"time"
+
+ "source.monogon.dev/go/logging"
)
func testPayload(msg string) *LeveledPayload {
return &LeveledPayload{
messages: []string{msg},
timestamp: time.Now(),
- severity: INFO,
+ severity: logging.INFO,
file: "main.go",
line: 1337,
}
diff --git a/osbase/logtree/klog.go b/osbase/logtree/klog.go
index ad7e162..dca5a82 100644
--- a/osbase/logtree/klog.go
+++ b/osbase/logtree/klog.go
@@ -24,6 +24,7 @@
"strings"
"time"
+ "source.monogon.dev/go/logging"
"source.monogon.dev/osbase/logbuffer"
)
@@ -47,7 +48,7 @@
// lines do not necessarily have their year aleays equal to the current year, as
// the code handles the edge case of parsing a line from the end of a previous
// year at the beginning of the next).
-func KLogParser(logger LeveledLogger) io.WriteCloser {
+func KLogParser(logger logging.Leveled) io.WriteCloser {
p, ok := logger.(*leveledPublisher)
if !ok {
// Fail fast, as this is a programming error.
@@ -121,16 +122,16 @@
lineS := parts[7]
message := parts[8]
- var severity Severity
+ var severity logging.Severity
switch severityS {
case "I":
- severity = INFO
+ severity = logging.INFO
case "W":
- severity = WARNING
+ severity = logging.WARNING
case "E":
- severity = ERROR
+ severity = logging.ERROR
case "F":
- severity = FATAL
+ severity = logging.FATAL
default:
return nil
}
diff --git a/osbase/logtree/klog_test.go b/osbase/logtree/klog_test.go
index d53df3f..788a7eb 100644
--- a/osbase/logtree/klog_test.go
+++ b/osbase/logtree/klog_test.go
@@ -21,6 +21,8 @@
"time"
"github.com/google/go-cmp/cmp"
+
+ "source.monogon.dev/go/logging"
)
func TestParse(t *testing.T) {
@@ -40,7 +42,7 @@
{now, "E0312 14:20:04.240540 204 shared_informer.go:247] Caches are synced for attach detach", &LeveledPayload{
messages: []string{"Caches are synced for attach detach"},
timestamp: time.Date(2021, 03, 12, 14, 20, 4, 240540000, time.UTC),
- severity: ERROR,
+ severity: logging.ERROR,
file: "shared_informer.go",
line: 247,
}},
@@ -56,7 +58,7 @@
{nowNewYear, "I1231 23:59:43.123456 123 fry.go:123] Here's to another lousy millenium!", &LeveledPayload{
messages: []string{"Here's to another lousy millenium!"},
timestamp: time.Date(1999, 12, 31, 23, 59, 43, 123456000, time.UTC),
- severity: INFO,
+ severity: logging.INFO,
file: "fry.go",
line: 123,
}},
@@ -68,7 +70,7 @@
{now, "E0312 14:20:04 204 shared_informer.go:247] Caches are synced for attach detach", &LeveledPayload{
messages: []string{"Caches are synced for attach detach"},
timestamp: time.Date(2021, 03, 12, 14, 20, 4, 0, time.UTC),
- severity: ERROR,
+ severity: logging.ERROR,
file: "shared_informer.go",
line: 247,
}},
diff --git a/osbase/logtree/kmsg.go b/osbase/logtree/kmsg.go
index 03bb6ff..11e140a 100644
--- a/osbase/logtree/kmsg.go
+++ b/osbase/logtree/kmsg.go
@@ -14,6 +14,8 @@
"time"
"golang.org/x/sys/unix"
+
+ "source.monogon.dev/go/logging"
)
const (
@@ -29,7 +31,7 @@
// KmsgPipe pipes logs from the kernel kmsg interface at /dev/kmsg into the
// given logger.
-func KmsgPipe(ctx context.Context, lt LeveledLogger) error {
+func KmsgPipe(ctx context.Context, lt logging.Leveled) error {
publisher, ok := lt.(*leveledPublisher)
if !ok {
// Fail fast, as this is a programming error.
@@ -119,18 +121,18 @@
monotonicFromNow := monotonic - monotonicSinceBoot
- var severity Severity
+ var severity logging.Severity
switch loglevel {
case loglevelEmergency, loglevelAlert:
- severity = FATAL
+ severity = logging.FATAL
case loglevelCritical, loglevelError:
- severity = ERROR
+ severity = logging.ERROR
case loglevelWarning:
- severity = WARNING
+ severity = logging.WARNING
case loglevelNotice, loglevelInfo, loglevelDebug:
- severity = INFO
+ severity = logging.INFO
default:
- severity = INFO
+ severity = logging.INFO
}
return &LeveledPayload{
diff --git a/osbase/logtree/kmsg_test.go b/osbase/logtree/kmsg_test.go
index e2faf82..24f2acf 100644
--- a/osbase/logtree/kmsg_test.go
+++ b/osbase/logtree/kmsg_test.go
@@ -8,6 +8,8 @@
"time"
"github.com/google/go-cmp/cmp"
+
+ "source.monogon.dev/go/logging"
)
func TestParseKmsg(t *testing.T) {
@@ -26,13 +28,13 @@
{"6,30962,1501094342185,-;test\n", &LeveledPayload{
messages: []string{"test"},
timestamp: time.Date(2023, 8, 9, 14, 57, 23, 35675222, time.UTC),
- severity: INFO,
+ severity: logging.INFO,
}},
// With metadata and different severity
{"4,30951,1486884175312,-;nvme nvme2: starting error recovery\n SUBSYSTEM=nvme\n DEVICE=c239:2\n", &LeveledPayload{
messages: []string{"nvme nvme2: starting error recovery"},
timestamp: time.Date(2023, 8, 9, 11, 00, 32, 868802222, time.UTC),
- severity: WARNING,
+ severity: logging.WARNING,
}},
} {
got := parseKmsg(now, nowMonotonic, []byte(te.line))
diff --git a/osbase/logtree/leveled.go b/osbase/logtree/leveled.go
index 98699b8..701d8d0 100644
--- a/osbase/logtree/leveled.go
+++ b/osbase/logtree/leveled.go
@@ -19,155 +19,34 @@
import (
"fmt"
+ "source.monogon.dev/go/logging"
lpb "source.monogon.dev/osbase/logtree/proto"
)
-// LeveledLogger is a generic interface for glog-style logging. There are four
-// hardcoded log severities, in increasing order: INFO, WARNING, ERROR, FATAL.
-// Logging at a certain severity level logs not only to consumers expecting data at
-// that severity level, but also all lower severity levels. For example, an ERROR
-// log will also be passed to consumers looking at INFO or WARNING logs.
-type LeveledLogger interface {
- // Info logs at the INFO severity. Arguments are handled in the manner of
- // fmt.Print, a terminating newline is added if missing.
- Info(args ...interface{})
- // Infof logs at the INFO severity. Arguments are handled in the manner of
- // fmt.Printf, a terminating newline is added if missing.
- Infof(format string, args ...interface{})
-
- // Warning logs at the WARNING severity. Arguments are handled in the manner of
- // fmt.Print, a terminating newline is added if missing.
- Warning(args ...interface{})
- // Warningf logs at the WARNING severity. Arguments are handled in the manner of
- // fmt.Printf, a terminating newline is added if missing.
- Warningf(format string, args ...interface{})
-
- // Error logs at the ERROR severity. Arguments are handled in the manner of
- // fmt.Print, a terminating newline is added if missing.
- Error(args ...interface{})
- // Errorf logs at the ERROR severity. Arguments are handled in the manner of
- // fmt.Printf, a terminating newline is added if missing.
- Errorf(format string, args ...interface{})
-
- // Fatal logs at the FATAL severity and aborts the current program. Arguments are
- // handled in the manner of fmt.Print, a terminating newline is added if missing.
- Fatal(args ...interface{})
- // Fatalf logs at the FATAL severity and aborts the current program. Arguments are
- // handled in the manner of fmt.Printf, a terminating newline is added if missing.
- Fatalf(format string, args ...interface{})
-
- // V returns a VerboseLeveledLogger at a given verbosity level. These verbosity
- // levels can be dynamically set and unset on a package-granular level by consumers
- // of the LeveledLogger logs. The returned value represents whether logging at the
- // given verbosity level was active at that time, and as such should not be a long-
- // lived object in programs. This construct is further refered to as 'V-logs'.
- V(level VerbosityLevel) VerboseLeveledLogger
-
- // WithAddedStackDepth returns the same LeveledLogger, but adjusted with an
- // additional 'extra stack depth' which will be used to skip a given number of
- // stack/call frames when determining the location where the error originated.
- // For example, WithStackDepth(1) will return a logger that will skip one
- // stack/call frame. Then, with function foo() calling function helper() which
- // in turns call l.Infof(), the log line will be emitted with the call site of
- // helper() within foo(), instead of the default behaviour of logging the
- // call site of Infof() within helper().
- //
- // This is useful for functions which somehow wrap loggers in helper functions,
- // for example to expose a slightly different API.
- WithAddedStackDepth(depth int) LeveledLogger
-}
-
-// VerbosityLevel is a verbosity level defined for V-logs. This can be changed
-// programmatically per Go package. When logging at a given VerbosityLevel V, the
-// current level must be equal or higher to V for the logs to be recorded.
-// Conversely, enabling a V-logging at a VerbosityLevel V also enables all logging
-// at lower levels [Int32Min .. (V-1)].
-type VerbosityLevel int32
-
-type VerboseLeveledLogger interface {
- // Enabled returns if this level was enabled. If not enabled, all logging into this
- // logger will be discarded immediately. Thus, Enabled() can be used to check the
- // verbosity level before performing any logging:
- // if l.V(3).Enabled() { l.Info("V3 is enabled") }
- // or, in simple cases, the convenience function .Info can be used:
- // l.V(3).Info("V3 is enabled")
- // The second form is shorter and more convenient, but more expensive, as its
- // arguments are always evaluated.
- Enabled() bool
- // Info is the equivalent of a LeveledLogger's Info call, guarded by whether this
- // VerboseLeveledLogger is enabled.
- Info(args ...interface{})
- // Infof is the equivalent of a LeveledLogger's Infof call, guarded by whether this
- // VerboseLeveledLogger is enabled.
- Infof(format string, args ...interface{})
-}
-
-// Severity is one of the severities as described in LeveledLogger.
-type Severity string
-
-const (
- INFO Severity = "I"
- WARNING Severity = "W"
- ERROR Severity = "E"
- FATAL Severity = "F"
-)
-
-var (
- // SeverityAtLeast maps a given severity to a list of severities that at that
- // severity or higher. In other words, SeverityAtLeast[X] returns a list of
- // severities that might be seen in a log at severity X.
- SeverityAtLeast = map[Severity][]Severity{
- INFO: {INFO, WARNING, ERROR, FATAL},
- WARNING: {WARNING, ERROR, FATAL},
- ERROR: {ERROR, FATAL},
- FATAL: {FATAL},
- }
-)
-
-func (s Severity) AtLeast(other Severity) bool {
- for _, el := range SeverityAtLeast[other] {
- if el == s {
- return true
- }
- }
- return false
-}
-
-// Valid returns whether true if this severity is one of the known levels
-// (INFO, WARNING, ERROR or FATAL), false otherwise.
-func (s Severity) Valid() bool {
- switch s {
- case INFO, WARNING, ERROR, FATAL:
- return true
- default:
- return false
- }
-}
-
-func SeverityFromProto(s lpb.LeveledLogSeverity) (Severity, error) {
+func SeverityFromProto(s lpb.LeveledLogSeverity) (logging.Severity, error) {
switch s {
case lpb.LeveledLogSeverity_INFO:
- return INFO, nil
+ return logging.INFO, nil
case lpb.LeveledLogSeverity_WARNING:
- return WARNING, nil
+ return logging.WARNING, nil
case lpb.LeveledLogSeverity_ERROR:
- return ERROR, nil
+ return logging.ERROR, nil
case lpb.LeveledLogSeverity_FATAL:
- return FATAL, nil
+ return logging.FATAL, nil
default:
return "", fmt.Errorf("unknown severity value %d", s)
}
}
-func (s Severity) ToProto() lpb.LeveledLogSeverity {
+func SeverityToProto(s logging.Severity) lpb.LeveledLogSeverity {
switch s {
- case INFO:
+ case logging.INFO:
return lpb.LeveledLogSeverity_INFO
- case WARNING:
+ case logging.WARNING:
return lpb.LeveledLogSeverity_WARNING
- case ERROR:
+ case logging.ERROR:
return lpb.LeveledLogSeverity_ERROR
- case FATAL:
+ case logging.FATAL:
return lpb.LeveledLogSeverity_FATAL
default:
return lpb.LeveledLogSeverity_INVALID
diff --git a/osbase/logtree/leveled_payload.go b/osbase/logtree/leveled_payload.go
index 95b9d5c..b038848 100644
--- a/osbase/logtree/leveled_payload.go
+++ b/osbase/logtree/leveled_payload.go
@@ -24,6 +24,7 @@
tpb "google.golang.org/protobuf/types/known/timestamppb"
+ "source.monogon.dev/go/logging"
lpb "source.monogon.dev/osbase/logtree/proto"
)
@@ -38,7 +39,7 @@
// timestamp is the time at which this message was emitted.
timestamp time.Time
// severity is the leveled Severity at which this message was emitted.
- severity Severity
+ severity logging.Severity
// file is the filename of the caller that emitted this message.
file string
// line is the line number within the file of the caller that emitted this message.
@@ -111,14 +112,14 @@
func (p *LeveledPayload) Location() string { return fmt.Sprintf("%s:%d", p.file, p.line) }
// Severity returns the Severity with which this entry was logged.
-func (p *LeveledPayload) Severity() Severity { return p.severity }
+func (p *LeveledPayload) Severity() logging.Severity { return p.severity }
// Proto converts a LeveledPayload to protobuf format.
func (p *LeveledPayload) Proto() *lpb.LogEntry_Leveled {
return &lpb.LogEntry_Leveled{
Lines: p.Messages(),
Timestamp: tpb.New(p.Timestamp()),
- Severity: p.Severity().ToProto(),
+ Severity: SeverityToProto(p.Severity()),
Location: p.Location(),
}
}
@@ -167,7 +168,7 @@
// given, will default to the time of conversion to LeveledPayload.
Timestamp time.Time
// Log severity. If invalid or unset will default to INFO.
- Severity Severity
+ Severity logging.Severity
// File name of originating code. Defaults to "unknown" if not set.
File string
// Line in File. Zero indicates the line is not known.
@@ -188,7 +189,7 @@
l.timestamp = time.Now()
}
if !l.severity.Valid() {
- l.severity = INFO
+ l.severity = logging.INFO
}
if l.file == "" {
l.file = "unknown"
diff --git a/osbase/logtree/logtree.go b/osbase/logtree/logtree.go
index c20681d..b6f8a06 100644
--- a/osbase/logtree/logtree.go
+++ b/osbase/logtree/logtree.go
@@ -21,6 +21,7 @@
"strings"
"sync"
+ "source.monogon.dev/go/logging"
"source.monogon.dev/osbase/logbuffer"
)
@@ -52,7 +53,7 @@
tree *LogTree
// verbosity is the current verbosity level of this DN/node, affecting .V(n)
// LeveledLogger calls
- verbosity VerbosityLevel
+ verbosity logging.VerbosityLevel
rawLineBuffer *logbuffer.LineBuffer
// mu guards children.
diff --git a/osbase/logtree/logtree_access.go b/osbase/logtree/logtree_access.go
index b601ea4..30ceccf 100644
--- a/osbase/logtree/logtree_access.go
+++ b/osbase/logtree/logtree_access.go
@@ -19,6 +19,8 @@
import (
"errors"
"sync/atomic"
+
+ "source.monogon.dev/go/logging"
)
// LogReadOption describes options for the LogTree.Read call.
@@ -28,7 +30,7 @@
withBacklog int
onlyLeveled bool
onlyRaw bool
- leveledWithMinimumSeverity Severity
+ leveledWithMinimumSeverity logging.Severity
}
// WithChildren makes Read return/stream data for both a given DN and all its
@@ -54,7 +56,7 @@
// LeveledWithMinimumSeverity makes Read return only log entries that are at least
// at a given Severity. If only leveled entries are needed, OnlyLeveled must be
// used. This is a no-op when OnlyRaw is used.
-func LeveledWithMinimumSeverity(s Severity) LogReadOption {
+func LeveledWithMinimumSeverity(s logging.Severity) LogReadOption {
return LogReadOption{leveledWithMinimumSeverity: s}
}
@@ -111,7 +113,7 @@
var backlog int
var stream bool
var recursive bool
- var leveledSeverity Severity
+ var leveledSeverity logging.Severity
var onlyRaw, onlyLeveled bool
for _, opt := range opts {
diff --git a/osbase/logtree/logtree_publisher.go b/osbase/logtree/logtree_publisher.go
index 6c4120a..2df7037 100644
--- a/osbase/logtree/logtree_publisher.go
+++ b/osbase/logtree/logtree_publisher.go
@@ -23,6 +23,7 @@
"strings"
"time"
+ "source.monogon.dev/go/logging"
"source.monogon.dev/osbase/logbuffer"
)
@@ -33,7 +34,7 @@
// 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) {
+func (l *LogTree) LeveledFor(dn DN) (logging.Leveled, error) {
node, err := l.nodeByDN(dn)
if err != nil {
return nil, err
@@ -54,7 +55,7 @@
// MustLeveledFor returns a LeveledLogger publishing interface for a given DN, or
// panics if the given DN is invalid.
-func (l *LogTree) MustLeveledFor(dn DN) LeveledLogger {
+func (l *LogTree) MustLeveledFor(dn DN) logging.Leveled {
leveled, err := l.LeveledFor(dn)
if err != nil {
panic(fmt.Errorf("LeveledFor returned: %w", err))
@@ -72,7 +73,7 @@
// SetVerbosity sets the verbosity for a given DN (non-recursively, ie. for that DN
// only, not its children).
-func (l *LogTree) SetVerbosity(dn DN, level VerbosityLevel) error {
+func (l *LogTree) SetVerbosity(dn DN, level logging.VerbosityLevel) error {
node, err := l.nodeByDN(dn)
if err != nil {
return err
@@ -97,7 +98,7 @@
// LeveledLogger. This should only be used by systems which translate external
// data sources into leveled logging - see ExternelLeveledPayload for more
// information.
-func LogExternalLeveled(l LeveledLogger, e *ExternalLeveledPayload) error {
+func LogExternalLeveled(l logging.Leveled, e *ExternalLeveledPayload) error {
publisher, ok := l.(*leveledPublisher)
if !ok {
return fmt.Errorf("the given LeveledLogger is not a *leveledPublisher")
@@ -115,7 +116,7 @@
// 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 (l *leveledPublisher) logLeveled(depth int, severity Severity, msg string) {
+func (l *leveledPublisher) logLeveled(depth int, severity logging.Severity, msg string) {
_, file, line, ok := runtime.Caller(2 + depth)
if !ok {
file = "???"
@@ -147,53 +148,53 @@
// Info implements the LeveledLogger interface.
func (l *leveledPublisher) Info(args ...interface{}) {
- l.logLeveled(l.depth, INFO, fmt.Sprint(args...))
+ l.logLeveled(l.depth, logging.INFO, fmt.Sprint(args...))
}
// Infof implements the LeveledLogger interface.
func (l *leveledPublisher) Infof(format string, args ...interface{}) {
- l.logLeveled(l.depth, INFO, fmt.Sprintf(format, args...))
+ l.logLeveled(l.depth, logging.INFO, fmt.Sprintf(format, args...))
}
// Warning implements the LeveledLogger interface.
func (l *leveledPublisher) Warning(args ...interface{}) {
- l.logLeveled(l.depth, WARNING, fmt.Sprint(args...))
+ l.logLeveled(l.depth, logging.WARNING, fmt.Sprint(args...))
}
// Warningf implements the LeveledLogger interface.
func (l *leveledPublisher) Warningf(format string, args ...interface{}) {
- l.logLeveled(l.depth, WARNING, fmt.Sprintf(format, args...))
+ l.logLeveled(l.depth, logging.WARNING, fmt.Sprintf(format, args...))
}
// Error implements the LeveledLogger interface.
func (l *leveledPublisher) Error(args ...interface{}) {
- l.logLeveled(l.depth, ERROR, fmt.Sprint(args...))
+ l.logLeveled(l.depth, logging.ERROR, fmt.Sprint(args...))
}
// Errorf implements the LeveledLogger interface.
func (l *leveledPublisher) Errorf(format string, args ...interface{}) {
- l.logLeveled(l.depth, ERROR, fmt.Sprintf(format, args...))
+ l.logLeveled(l.depth, logging.ERROR, fmt.Sprintf(format, args...))
}
// Fatal implements the LeveledLogger interface.
func (l *leveledPublisher) Fatal(args ...interface{}) {
- l.logLeveled(l.depth, FATAL, fmt.Sprint(args...))
+ l.logLeveled(l.depth, logging.FATAL, fmt.Sprint(args...))
}
// Fatalf implements the LeveledLogger interface.
func (l *leveledPublisher) Fatalf(format string, args ...interface{}) {
- l.logLeveled(l.depth, FATAL, fmt.Sprintf(format, args...))
+ l.logLeveled(l.depth, logging.FATAL, fmt.Sprintf(format, args...))
}
// WithAddedStackDepth impleemnts the LeveledLogger interface.
-func (l *leveledPublisher) WithAddedStackDepth(depth int) LeveledLogger {
+func (l *leveledPublisher) WithAddedStackDepth(depth int) logging.Leveled {
l2 := *l
l2.depth += depth
return &l2
}
// V implements the LeveledLogger interface.
-func (l *leveledPublisher) V(v VerbosityLevel) VerboseLeveledLogger {
+func (l *leveledPublisher) V(v logging.VerbosityLevel) logging.VerboseLeveled {
return &verbose{
publisher: l,
enabled: l.node.verbosity >= v,
@@ -218,12 +219,12 @@
if !v.enabled {
return
}
- v.publisher.logLeveled(v.publisher.depth, INFO, fmt.Sprint(args...))
+ v.publisher.logLeveled(v.publisher.depth, logging.INFO, fmt.Sprint(args...))
}
func (v *verbose) Infof(format string, args ...interface{}) {
if !v.enabled {
return
}
- v.publisher.logLeveled(v.publisher.depth, INFO, fmt.Sprintf(format, args...))
+ v.publisher.logLeveled(v.publisher.depth, logging.INFO, fmt.Sprintf(format, args...))
}
diff --git a/osbase/logtree/logtree_test.go b/osbase/logtree/logtree_test.go
index 54eabb7..8ddd3d0 100644
--- a/osbase/logtree/logtree_test.go
+++ b/osbase/logtree/logtree_test.go
@@ -21,6 +21,8 @@
"strings"
"testing"
"time"
+
+ "source.monogon.dev/go/logging"
)
func expect(tree *LogTree, t *testing.T, dn DN, entries ...string) string {
@@ -227,13 +229,13 @@
for _, te := range []struct {
ix int
- severity Severity
+ severity logging.Severity
message string
}{
- {0, ERROR, "i am an error"},
- {1, WARNING, "i am a warning"},
- {2, INFO, "i am informative"},
- {3, INFO, "i am a zero-level debug"},
+ {0, logging.ERROR, "i am an error"},
+ {1, logging.WARNING, "i am a warning"},
+ {2, logging.INFO, "i am informative"},
+ {3, logging.INFO, "i am a zero-level debug"},
} {
p := reader.Backlog[te.ix]
if want, got := te.severity, p.Leveled.Severity(); want != got {
@@ -255,7 +257,7 @@
tree.MustLeveledFor("main").Info("i am informative")
tree.MustLeveledFor("main").V(0).Info("i am a zero-level debug")
- reader, err := tree.Read("main", WithBacklog(BacklogAllAvailable), LeveledWithMinimumSeverity(WARNING))
+ reader, err := tree.Read("main", WithBacklog(BacklogAllAvailable), LeveledWithMinimumSeverity(logging.WARNING))
if err != nil {
t.Fatalf("Read: %v", err)
}
@@ -311,7 +313,7 @@
&LogEntry{
Leveled: &LeveledPayload{
messages: []string{"Hello there!"},
- severity: WARNING,
+ severity: logging.WARNING,
},
DN: "root.role.kubernetes.run.kubernetes.apiserver",
},
@@ -322,7 +324,7 @@
&LogEntry{
Leveled: &LeveledPayload{
messages: []string{"Hello there!", "I am multiline."},
- severity: WARNING,
+ severity: logging.WARNING,
},
DN: "root.role.kubernetes.run.kubernetes.apiserver",
},
@@ -336,7 +338,7 @@
&LogEntry{
Leveled: &LeveledPayload{
messages: []string{"Hello there! I am a very long string, and I will get wrapped to 120 columns because that's just how life is for long strings."},
- severity: WARNING,
+ severity: logging.WARNING,
},
DN: "root.role.kubernetes.run.kubernetes.apiserver",
},
@@ -350,7 +352,7 @@
&LogEntry{
Leveled: &LeveledPayload{
messages: []string{"Hello there!"},
- severity: WARNING,
+ severity: logging.WARNING,
},
DN: "root.role.kubernetes.run.kubernetes.apiserver",
},
@@ -363,7 +365,7 @@
&LogEntry{
Leveled: &LeveledPayload{
messages: []string{"Hello there!"},
- severity: WARNING,
+ severity: logging.WARNING,
},
DN: "root.role.kubernetes.run.kubernetes.apiserver",
},
diff --git a/osbase/logtree/unraw/BUILD.bazel b/osbase/logtree/unraw/BUILD.bazel
index 3ae4da1..9364a30 100644
--- a/osbase/logtree/unraw/BUILD.bazel
+++ b/osbase/logtree/unraw/BUILD.bazel
@@ -6,6 +6,7 @@
importpath = "source.monogon.dev/osbase/logtree/unraw",
visibility = ["//visibility:public"],
deps = [
+ "//go/logging",
"//osbase/logbuffer",
"//osbase/logtree",
"//osbase/supervisor",
diff --git a/osbase/logtree/unraw/unraw.go b/osbase/logtree/unraw/unraw.go
index a1f2624..88ab9d1 100644
--- a/osbase/logtree/unraw/unraw.go
+++ b/osbase/logtree/unraw/unraw.go
@@ -24,6 +24,7 @@
"syscall"
"time"
+ "source.monogon.dev/go/logging"
"source.monogon.dev/osbase/logbuffer"
"source.monogon.dev/osbase/logtree"
"source.monogon.dev/osbase/supervisor"
@@ -51,7 +52,7 @@
MaximumLineLength int
// LeveledLogger is the logtree leveled logger into which events from the
// Parser will be sent.
- LeveledLogger logtree.LeveledLogger
+ LeveledLogger logging.Leveled
// mu guards lb.
mu sync.Mutex
diff --git a/osbase/logtree/zap.go b/osbase/logtree/zap.go
index f3ae6e3..82e6dda 100644
--- a/osbase/logtree/zap.go
+++ b/osbase/logtree/zap.go
@@ -10,13 +10,14 @@
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
+ "source.monogon.dev/go/logging"
"source.monogon.dev/osbase/logbuffer"
)
// Zapify turns a LeveledLogger into a zap.Logger which pipes its output into the
// LeveledLogger. The message, severity and caller are carried over. Extra fields
// are appended as JSON to the end of the log line.
-func Zapify(logger LeveledLogger, minimumLevel zapcore.Level) *zap.Logger {
+func Zapify(logger logging.Leveled, minimumLevel zapcore.Level) *zap.Logger {
p, ok := logger.(*leveledPublisher)
if !ok {
// Fail fast, as this is a programming error.
@@ -71,7 +72,7 @@
type zapEntry struct {
message string
- severity Severity
+ severity logging.Severity
time time.Time
file string
line int
@@ -109,14 +110,14 @@
callerLineS := callerParts[1]
callerLine, _ := strconv.Atoi(callerLineS)
- var severity Severity
+ var severity logging.Severity
switch level {
case "warn":
- severity = WARNING
+ severity = logging.WARNING
case "error", "dpanic", "panic", "fatal":
- severity = ERROR
+ severity = logging.ERROR
default:
- severity = INFO
+ severity = logging.INFO
}
secs := int64(t)
diff --git a/osbase/logtree/zap_test.go b/osbase/logtree/zap_test.go
index 3917cd8..b03b8cf 100644
--- a/osbase/logtree/zap_test.go
+++ b/osbase/logtree/zap_test.go
@@ -4,6 +4,8 @@
"testing"
"go.uber.org/zap"
+
+ "source.monogon.dev/go/logging"
)
func TestZapify(t *testing.T) {
@@ -25,11 +27,11 @@
} else {
for i, te := range []struct {
msg string
- sev Severity
+ sev logging.Severity
}{
- {`foo {"intp":42,"strp":"strv"}`, INFO},
- {`foo! {"intp":1337,"strp":"strv"}`, WARNING},
- {`foo!!`, ERROR},
+ {`foo {"intp":42,"strp":"strv"}`, logging.INFO},
+ {`foo! {"intp":1337,"strp":"strv"}`, logging.WARNING},
+ {`foo!!`, logging.ERROR},
} {
if want, got := te.msg, res.Backlog[i].Leveled.messages[0]; want != got {
t.Errorf("Line %d: wanted message %q, got %q", i, want, got)
diff --git a/osbase/supervisor/BUILD.bazel b/osbase/supervisor/BUILD.bazel
index b6b4861..9dfda5a 100644
--- a/osbase/supervisor/BUILD.bazel
+++ b/osbase/supervisor/BUILD.bazel
@@ -15,6 +15,7 @@
# TODO(#189): move supervisor to //go
visibility = ["//visibility:public"],
deps = [
+ "//go/logging",
"//osbase/logtree",
"@com_github_cenkalti_backoff_v4//:backoff",
"@com_github_prometheus_client_golang//prometheus",
diff --git a/osbase/supervisor/supervisor.go b/osbase/supervisor/supervisor.go
index ff87a25..5570945 100644
--- a/osbase/supervisor/supervisor.go
+++ b/osbase/supervisor/supervisor.go
@@ -27,6 +27,7 @@
"io"
"sync"
+ "source.monogon.dev/go/logging"
"source.monogon.dev/osbase/logtree"
)
@@ -94,7 +95,7 @@
// 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
+ ilogger logging.Leveled
// pReq is an interface channel to the lifecycle processor of the
// supervisor.
@@ -160,7 +161,7 @@
return sup
}
-func Logger(ctx context.Context) logtree.LeveledLogger {
+func Logger(ctx context.Context) logging.Leveled {
node, unlock := fromContext(ctx)
defer unlock()
return node.sup.logtree.MustLeveledFor(logtree.DN(node.dn()))
@@ -182,7 +183,7 @@
// sub-logger with a given name, that name also becomes unavailable for use as
// a child runnable (no runnable and sub-logger may ever log into the same
// logtree DN).
-func SubLogger(ctx context.Context, name string) (logtree.LeveledLogger, error) {
+func SubLogger(ctx context.Context, name string) (logging.Leveled, error) {
node, unlock := fromContext(ctx)
defer unlock()
@@ -201,7 +202,7 @@
// MustSubLogger is a wrapper around SubLogger which panics on error. Errors
// should only happen due to invalid names, so as long as the given name is
// compile-time constant and valid, this function is safe to use.
-func MustSubLogger(ctx context.Context, name string) logtree.LeveledLogger {
+func MustSubLogger(ctx context.Context, name string) logging.Leveled {
l, err := SubLogger(ctx, name)
if err != nil {
panic(err)
diff --git a/osbase/tpm/BUILD.bazel b/osbase/tpm/BUILD.bazel
index d75c9fb..6f33dca 100644
--- a/osbase/tpm/BUILD.bazel
+++ b/osbase/tpm/BUILD.bazel
@@ -9,7 +9,7 @@
importpath = "source.monogon.dev/osbase/tpm",
visibility = ["//visibility:public"],
deps = [
- "//osbase/logtree",
+ "//go/logging",
"//osbase/sysfs",
"//osbase/tpm/proto",
"@com_github_google_go_tpm//tpm2",
diff --git a/osbase/tpm/tpm.go b/osbase/tpm/tpm.go
index b77c36d..f664c75 100644
--- a/osbase/tpm/tpm.go
+++ b/osbase/tpm/tpm.go
@@ -41,7 +41,7 @@
tpmpb "source.monogon.dev/osbase/tpm/proto"
- "source.monogon.dev/osbase/logtree"
+ "source.monogon.dev/go/logging"
"source.monogon.dev/osbase/sysfs"
)
@@ -126,7 +126,7 @@
// TPM represents a high-level interface to a connected TPM 2.0
type TPM struct {
- logger logtree.LeveledLogger
+ logger logging.Leveled
device io.ReadWriteCloser
// We keep the AK loaded since it's used fairly often and deriving it is
@@ -137,7 +137,7 @@
// Initialize finds and opens the TPM (if any). If there is no TPM available it
// returns ErrNotExists
-func Initialize(logger logtree.LeveledLogger) error {
+func Initialize(logger logging.Leveled) error {
lock.Lock()
defer lock.Unlock()
tpmDir, err := os.Open("/sys/class/tpm")