"The query log holds 7 answers (stats.retention.queries)" read like 7 days' worth. The dashboard and the Statistics page now say how many answers it holds and how long each is kept; the dashboard's storage info has query_log_retention. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
80 lines
2.2 KiB
Go
80 lines
2.2 KiB
Go
package server
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"path/filepath"
|
|
"slices"
|
|
|
|
"jarl/internal/api"
|
|
"jarl/internal/stats"
|
|
)
|
|
|
|
// storage reports the size of Jarl's databases and how full the disks
|
|
// Jarl uses are (the dashboard's Storage card).
|
|
func (s *Server) storage(ctx context.Context) *api.Storage {
|
|
out := &api.Storage{Databases: []api.Database{}, Disks: []api.Disk{}}
|
|
dbFile := func(label, path string) *api.Database {
|
|
if path == "" || path == ":memory:" {
|
|
return nil
|
|
}
|
|
d := api.Database{Label: label, Path: path, Bytes: dbBytes(path)}
|
|
out.Databases = append(out.Databases, d)
|
|
out.Total += d.Bytes
|
|
return &out.Databases[len(out.Databases)-1]
|
|
}
|
|
labels := []string{}
|
|
dirs := map[string]string{}
|
|
add := func(label, dir string) {
|
|
if dir != "" {
|
|
labels = append(labels, label)
|
|
dirs[label] = dir
|
|
}
|
|
}
|
|
const jarlDB, statsDB = "Jarl's database", "statistics database"
|
|
if p := s.store.Path(); p != "" {
|
|
dbFile(jarlDB, p)
|
|
add(jarlDB, filepath.Dir(p))
|
|
}
|
|
if s.cfg.Stats != nil {
|
|
if p := s.cfg.Stats.Store().Path(); p != "" && p != ":memory:" {
|
|
if d := dbFile(statsDB, p); d != nil && s.cfg.Stats.Options().RetainQueries > 0 {
|
|
if n, err := s.cfg.Stats.Store().QueryLogSize(ctx); err == nil {
|
|
d.QueryLogRows = &n
|
|
d.QueryLogRetention = s.cfg.Stats.Status().Retention.Queries
|
|
}
|
|
}
|
|
add(statsDB, filepath.Dir(p))
|
|
}
|
|
if lf := s.cfg.Stats.Options().LogFile; lf != "" {
|
|
add("named's logs", filepath.Dir(lf))
|
|
}
|
|
}
|
|
paths := s.eng.Config().Paths
|
|
add("zone files", paths.ZoneDir)
|
|
add("named.conf", paths.ConfigDir)
|
|
add("Jarl's cache and blocklists", paths.CacheDir)
|
|
add("backups", s.cfg.BackupDir)
|
|
for _, d := range stats.DiskUsage(labels, dirs) {
|
|
disk := api.Disk{Path: d.Path, Holds: d.Holds, Total: d.Total, Free: d.Free}
|
|
for _, db := range out.Databases {
|
|
if slices.Contains(d.Holds, db.Label) {
|
|
disk.Databases += db.Bytes
|
|
}
|
|
}
|
|
out.Disks = append(out.Disks, disk)
|
|
}
|
|
return out
|
|
}
|
|
|
|
// dbBytes is the size of a SQLite database: its file, -wal and -shm.
|
|
func dbBytes(path string) int64 {
|
|
var n int64
|
|
for _, suffix := range []string{"", "-wal", "-shm"} {
|
|
if fi, err := os.Stat(path + suffix); err == nil {
|
|
n += fi.Size()
|
|
}
|
|
}
|
|
return n
|
|
}
|