github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/pkg/util/debug/debug.go (about) 1 package debug 2 3 import ( 4 "time" 5 6 "github.com/prometheus/client_golang/prometheus" 7 "github.com/prometheus/client_golang/prometheus/promauto" 8 "github.com/shirou/gopsutil/cpu" 9 "github.com/sirupsen/logrus" 10 11 "github.com/pyroscope-io/pyroscope/pkg/build" 12 "github.com/pyroscope-io/pyroscope/pkg/storage" 13 ) 14 15 // TODO(kolesnikovae): Get rid of it? 16 17 const debugInfoReportingInterval = 30 * time.Second 18 19 type Reporter struct { 20 logger *logrus.Logger 21 storage *storage.Storage 22 stop chan struct{} 23 done chan struct{} 24 } 25 26 func NewReporter(l *logrus.Logger, s *storage.Storage, reg prometheus.Registerer) *Reporter { 27 promauto.With(reg).NewGaugeFunc( 28 prometheus.GaugeOpts{ 29 Name: "pyroscope_build_info", 30 Help: "A metric with a constant '1' value labeled by version, revision and other info from which pyroscope was built.", 31 ConstLabels: build.PrometheusBuildLabels(), 32 }, 33 func() float64 { return 1 }, 34 ) 35 36 return &Reporter{ 37 storage: s, 38 logger: l, 39 stop: make(chan struct{}), 40 done: make(chan struct{}), 41 } 42 } 43 44 func (d *Reporter) Stop() { 45 close(d.stop) 46 <-d.done 47 } 48 49 func (d *Reporter) Start() { 50 defer close(d.done) 51 ticker := time.NewTicker(debugInfoReportingInterval) 52 defer ticker.Stop() 53 for { 54 select { 55 case <-d.stop: 56 return 57 case <-ticker.C: 58 // TODO(kolesnikovae): refactor CPUUsage blocks for debugInfoReportingInterval. 59 // d.logger.WithField("utilization", CPUUsage(debugInfoReportingInterval)).Debug("cpu stats") 60 d.logger.WithFields(d.diskUsageFields()).Debug("disk usage") 61 d.logger.WithFields(d.cacheStatsFields()).Debug("cache stats") 62 } 63 } 64 } 65 66 func CPUUsage(interval time.Duration) float64 { 67 if v, err := cpu.Percent(interval, false); err == nil && len(v) > 0 { 68 return v[0] 69 } 70 return 0 71 } 72 73 func (d *Reporter) diskUsageFields() logrus.Fields { 74 fields := make(logrus.Fields) 75 for k, v := range d.storage.DiskUsage() { 76 fields[k] = v 77 } 78 return fields 79 } 80 81 func (d *Reporter) cacheStatsFields() logrus.Fields { 82 fields := make(logrus.Fields) 83 for k, v := range d.storage.CacheStats() { 84 fields[k] = v 85 } 86 return fields 87 }