func logLinuxStats() { if !log.V(1) { return } // We don't know which fields in struct mallinfo are most relevant to us yet, // so log it all for now. // // A major caveat is that mallinfo() returns stats only for the main arena. // glibc uses multiple allocation arenas to increase malloc performance for // multithreaded processes, so mallinfo may not report on significant parts // of the heap. mi := C.mallinfo() log.Infof("mallinfo stats: ordblks=%s, smblks=%s, hblks=%s, hblkhd=%s, usmblks=%s, fsmblks=%s, "+ "uordblks=%s, fordblks=%s, keepcost=%s", humanize.IBytes(uint64(mi.ordblks)), humanize.IBytes(uint64(mi.smblks)), humanize.IBytes(uint64(mi.hblks)), humanize.IBytes(uint64(mi.hblkhd)), humanize.IBytes(uint64(mi.usmblks)), humanize.IBytes(uint64(mi.fsmblks)), humanize.IBytes(uint64(mi.uordblks)), humanize.IBytes(uint64(mi.fordblks)), humanize.IBytes(uint64(mi.fsmblks))) // malloc_info() emits a *lot* of XML, partly because it generates stats for // all arenas, unlike mallinfo(). // // TODO(cdo): extract the useful bits and record to time-series DB. if !log.V(2) { return } // Create a memstream and make malloc_info() output to it. var buf *C.char var bufSize C.size_t memstream := C.open_memstream(&buf, &bufSize) if memstream == nil { log.Warning("couldn't open memstream") return } defer func() { C.fclose(memstream) C.free(unsafe.Pointer(buf)) }() if rc := C.malloc_info(0, memstream); rc != 0 { log.Warningf("malloc_info returned %d", rc) return } if rc := C.fflush(memstream); rc != 0 { log.Warningf("fflush returned %d", rc) return } log.Infof("malloc_info: %s", C.GoString(buf)) }
// Handles the message "sistats". // Returns: // unencrypted reply func sistats() *xml.Hash { stats := xml.NewHash("xml", "header", "answer") stats.Add("source", config.ServerSourceAddress) stats.Add("target", "GOSA") answer := stats.Add("answer1") answer.Add("Version", config.Version) answer.Add("Revision", config.Revision) answer.Add("Uptime", time.Since(startTime)) answer.Add("Compiler", runtime.Compiler) answer.Add("Go-Version", runtime.Version()) answer.Add("Architecture", runtime.GOARCH) answer.Add("OS", runtime.GOOS) answer.Add("NumCPU", runtime.NumCPU()) answer.Add("NumGoroutine", runtime.NumGoroutine()) answer.Add("AvgRequestTime", time.Duration((atomic.LoadInt64(&RequestProcessingTime)+50)/100)) susipeers := 0 susipeersdown := 0 nonsusipeers := 0 nonsusipeersdown := 0 for _, addr := range db.ServerAddresses() { if Peer(addr).Downtime() == 0 { if Peer(addr).IsGoSusi() { susipeers++ } else { nonsusipeers++ } } else { if Peer(addr).IsGoSusi() { susipeersdown++ } else { nonsusipeersdown++ } } } answer.Add("SusiPeersUp", susipeers) answer.Add("SusiPeersDown", susipeersdown) answer.Add("NonSusiPeersUp", nonsusipeers) answer.Add("NonSusiPeersDown", nonsusipeersdown) var clistats ClientStats db.ClientsQuery(&clistats) time.Sleep(2 * time.Second) // give Up checks time to succeed answer.Add("KnownClients", clistats.KnownClients) answer.Add("KnownTLSClients", clistats.KnownTLSClients) up := atomic.LoadInt32(&clistats.MyClientsUp) answer.Add("MyClientsUp", up) answer.Add("MyClientsDown", clistats.MyClients-int(up)) answer.Add("TotalRegistrations", atomic.LoadInt32(&TotalRegistrations)) answer.Add("MissedRegistrations", atomic.LoadInt32(&MissedRegistrations)) var m runtime.MemStats runtime.ReadMemStats(&m) answer.Add("Alloc", m.Alloc) answer.Add("TotalAlloc", m.TotalAlloc) answer.Add("Sys", m.Sys) answer.Add("Lookups", m.Lookups) answer.Add("Mallocs", m.Mallocs) answer.Add("Frees", m.Frees) answer.Add("HeapAlloc", m.HeapAlloc) answer.Add("HeapSys", m.HeapSys) answer.Add("HeapIdle", m.HeapIdle) answer.Add("HeapInuse", m.HeapInuse) answer.Add("HeapReleased", m.HeapReleased) answer.Add("HeapObjects", m.HeapObjects) answer.Add("StackInuse", m.StackInuse) answer.Add("StackSys", m.StackSys) answer.Add("MSpanInuse", m.MSpanInuse) answer.Add("MSpanSys", m.MSpanSys) answer.Add("MCacheInuse", m.MCacheInuse) answer.Add("MCacheSys", m.MCacheSys) answer.Add("BuckHashSys", m.BuckHashSys) answer.Add("NextGC", m.NextGC) answer.Add("LastGC", m.LastGC) answer.Add("PauseTotalNs", m.PauseTotalNs) answer.Add("NumGC", m.NumGC) answer.Add("EnableGC", m.EnableGC) answer.Add("DebugGC", m.DebugGC) mallinfo := C.mallinfo() answer.Add("mallinfo_arena", mallinfo.arena) answer.Add("mallinfo_ordblks", mallinfo.ordblks) answer.Add("mallinfo_hblks", mallinfo.hblks) answer.Add("mallinfo_hblkhd", mallinfo.hblkhd) answer.Add("mallinfo_uordblks", mallinfo.uordblks) answer.Add("mallinfo_fordblks", mallinfo.fordblks) answer.Add("mallinfo_keepcost", mallinfo.keepcost) return stats }