text search for the atmosphere
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106package stats
import ( "log/slog" "sort" "sync")
// Stats counts records per NSID across four buckets:// - seen: every create/update commit that reached us// - blocked: dropped by the NSID blocklist// - indexed: passed blocklist, had prose, sent to Meili// - notext: passed blocklist, extraction produced no text//// seen == blocked + indexed + notext.type Stats struct { mu sync.Mutex seen map[string]uint64 blocked map[string]uint64 indexed map[string]uint64 notext map[string]uint64}
func New() *Stats { return &Stats{ seen: map[string]uint64{}, blocked: map[string]uint64{}, indexed: map[string]uint64{}, notext: map[string]uint64{}, }}
func (s *Stats) Seen(nsid string) { s.inc(s.seen, nsid) }func (s *Stats) Blocked(nsid string) { s.inc(s.blocked, nsid) }func (s *Stats) Indexed(nsid string) { s.inc(s.indexed, nsid) }func (s *Stats) NoText(nsid string) { s.inc(s.notext, nsid) }
func (s *Stats) inc(m map[string]uint64, nsid string) { s.mu.Lock() m[nsid]++ s.mu.Unlock()}
type Row struct { NSID string Count uint64}
// TopN returns the highest-count entries in a bucket.func (s *Stats) TopN(bucket string, n int) []Row { s.mu.Lock() defer s.mu.Unlock() var m map[string]uint64 switch bucket { case "seen": m = s.seen case "blocked": m = s.blocked case "indexed": m = s.indexed case "notext": m = s.notext default: return nil } rows := make([]Row, 0, len(m)) for k, v := range m { rows = append(rows, Row{NSID: k, Count: v}) } sort.Slice(rows, func(i, j int) bool { return rows[i].Count > rows[j].Count }) if len(rows) > n { rows = rows[:n] } return rows}
func (s *Stats) totals() (seen, blocked, indexed, notext uint64) { s.mu.Lock() defer s.mu.Unlock() for _, v := range s.seen { seen += v } for _, v := range s.blocked { blocked += v } for _, v := range s.indexed { indexed += v } for _, v := range s.notext { notext += v } return}
// LogSummary emits a compact per-bucket top-N to the logger.func (s *Stats) LogSummary(log *slog.Logger, n int) { seen, blocked, indexed, notext := s.totals() log.Info("stats totals", "seen", seen, "blocked", blocked, "indexed", indexed, "no_text", notext) for _, bucket := range []string{"indexed", "notext", "seen", "blocked"} { rows := s.TopN(bucket, n) for i, r := range rows { log.Info("stats top", "bucket", bucket, "rank", i+1, "nsid", r.NSID, "count", r.Count) } }}