m/pkg/logtree: implement concise stringification
This adds a new method on LogEntry: ConciseString(). It's designed to
be used in cases where we want to display the log line on some
limited-width (and likely non-interactive) log console, like TTY
consoles in Metropolis.
This is a bit too Metropolis-specific to my liking (we hardcode some
logic related to the layout of root.role.*), but it'll do for now.
Change-Id: I1079b8b19a3c304fcc5077ce6b4c69887a34d7ae
Reviewed-on: https://review.monogon.dev/c/monogon/+/1359
Reviewed-by: Leopold Schabel <leo@monogon.tech>
Tested-by: Jenkins CI
diff --git a/metropolis/pkg/logtree/journal.go b/metropolis/pkg/logtree/journal.go
index d29fdaa..5df6e1a 100644
--- a/metropolis/pkg/logtree/journal.go
+++ b/metropolis/pkg/logtree/journal.go
@@ -59,21 +59,25 @@
// represented by heads[DN]/tails[DN] pointers in journal and nextLocal/prevLocal
// pointers in entries:
//
-// .------------. .------------. .------------.
-// | dn: A.B | | dn: Z | | dn: A.B |
-// | time: 1 | | time: 2 | | time: 3 |
-// |------------| |------------| |------------|
-// | nextGlobal :------->| nextGlobal :------->| nextGlobal :--> nil
+// .------------. .------------. .------------.
+// | dn: A.B | | dn: Z | | dn: A.B |
+// | time: 1 | | time: 2 | | time: 3 |
+// |------------| |------------| |------------|
+// | nextGlobal :------->| nextGlobal :------->| nextGlobal :--> nil
+//
// nil <-: prevGlobal |<-------: prevGlobal |<-------| prevGlobal |
-// |------------| |------------| n |------------|
-// | nextLocal :---. n | nextLocal :->i .-->| nextLocal :--> nil
+//
+// |------------| |------------| n |------------|
+// | nextLocal :---. n | nextLocal :->i .-->| nextLocal :--> nil
+//
// nil <-: prevLocal |<--: i<-: prevLocal | l :---| prevLocal |
-// '------------' | l '------------' | '------------'
-// ^ '----------------------' ^
-// | ^ |
-// | | |
-// ( head ) ( tails[Z] ) ( tail )
-// ( heads[A.B] ) ( heads[Z] ) ( tails[A.B] )
+//
+// '------------' | l '------------' | '------------'
+// ^ '----------------------' ^
+// | ^ |
+// | | |
+// ( head ) ( tails[Z] ) ( tail )
+// ( heads[A.B] ) ( heads[Z] ) ( tails[A.B] )
type journal struct {
// mu locks the rest of the structure. It must be taken during any operation on the
// journal.
@@ -232,3 +236,70 @@
}
}
+
+// Shorten returns a shortened version of this DN for constrained logging
+// environments like tty0 logging.
+//
+// If ShortenDictionary is given, it will be used to replace DN parts with
+// shorter equivalents. For example, with the dictionary:
+//
+// { "foobar": "foo", "manager": "mgr" }
+//
+// The DN some.foobar.logger will be turned into some.foo.logger before further
+// being processed by the shortening mechanism.
+//
+// The shortening rules applied are Metropolis-specific.
+func (d DN) Shorten(dict ShortenDictionary, maxLen int) string {
+ path, _ := d.Path()
+ // Apply DN part shortening rules.
+ if dict != nil {
+ for i, p := range path {
+ if sh, ok := dict[p]; ok {
+ path[i] = sh
+ }
+ }
+ }
+
+ // This generally shouldn't happen.
+ if len(path) == 0 {
+ return "?"
+ }
+
+ // Strip 'root.' prefix.
+ if len(path) > 1 && path[0] == "root" {
+ path = path[1:]
+ }
+
+ // Replace role.xxx.yyy.zzz with xxx.zzz - stripping everything between the role
+ // name and the last element of the path.
+ if path[0] == "role" && len(path) > 1 {
+ if len(path) == 2 {
+ path = path[1:]
+ } else {
+ path = []string{
+ path[1],
+ path[len(path)-1],
+ }
+ }
+ }
+
+ // Join back to be ' '-delimited, and ellipsize if too long.
+ s := strings.Join(path, " ")
+ if overflow := len(s) - maxLen; overflow > 0 {
+ s = "..." + s[overflow+3:]
+ }
+ return s
+}
+
+type ShortenDictionary map[string]string
+
+var MetropolisShortenDict = ShortenDictionary{
+ "controlplane": "cplane",
+ "map-cluster-membership": "map-membership",
+ "cluster-membership": "cluster",
+ "controller-manager": "controllers",
+ "networking": "net",
+ "network": "net",
+ "interfaces": "ifaces",
+ "kubernetes": "k8s",
+}