util/lru, util/limiter: add debug helper to dump state as HTML

For use in tsweb debug handlers, so that we can easily inspect cache
and limiter state when troubleshooting.

Updates tailscale/corp#3601

Signed-off-by: David Anderson <danderson@tailscale.com>
This commit is contained in:
David Anderson
2023-09-07 17:33:02 -07:00
committed by Dave Anderson
parent d23b8ffb13
commit 95082a8dde
4 changed files with 178 additions and 0 deletions

View File

@ -4,6 +4,12 @@
// Package lru contains a typed Least-Recently-Used cache.
package lru
import (
"fmt"
"html"
"io"
)
// Cache is container type keyed by K, storing V, optionally evicting the least
// recently used items if a maximum size is exceeded.
//
@ -171,3 +177,31 @@ func (c *Cache[K, V]) deleteElement(ent *entry[K, V]) {
}
delete(c.lookup, ent.key)
}
// ForEach calls fn for each entry in the cache, from most recently
// used to least recently used.
func (c *Cache[K, V]) ForEach(fn func(K, V)) {
if c.head == nil {
return
}
cur := c.head
for {
fn(cur.key, cur.value)
cur = cur.next
if cur == c.head {
return
}
}
}
// DumpHTML writes the state of the cache to the given writer,
// formatted as an HTML table.
func (c *Cache[K, V]) DumpHTML(w io.Writer) {
io.WriteString(w, "<table><tr><th>Key</th><th>Value</th></tr>")
c.ForEach(func(k K, v V) {
kStr := html.EscapeString(fmt.Sprint(k))
vStr := html.EscapeString(fmt.Sprint(v))
fmt.Fprintf(w, "<tr><td>%s</td><td>%v</td></tr>", kStr, vStr)
})
io.WriteString(w, "</table>")
}