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  }