github.com/kaydxh/golang@v0.0.131/pkg/monitor/opentelemetry/resource/resource.stats.go (about)

     1  package resource
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"sync"
     7  	"sync/atomic"
     8  	"time"
     9  
    10  	"github.com/kaydxh/golang/go/errors"
    11  	time_ "github.com/kaydxh/golang/go/time"
    12  	"github.com/sirupsen/logrus"
    13  )
    14  
    15  const (
    16  	DefaultCheckInterval time.Duration = time.Minute
    17  )
    18  
    19  type ResourceStatsOptions struct {
    20  	checkInterval  time.Duration
    21  	memoryCallBack func(total, free uint64, usage float64)
    22  }
    23  
    24  type ResourceStatsService struct {
    25  	inShutdown atomic.Bool // true when when server is in shutdown
    26  
    27  	opts ResourceStatsOptions
    28  
    29  	metrics *ResourceStatsMetrics
    30  
    31  	mu     sync.Mutex
    32  	cancel func()
    33  }
    34  
    35  func NewResourceStatsService(opts ...ResourceStatsServiceOption) (*ResourceStatsService, error) {
    36  	var err error
    37  	r := &ResourceStatsService{}
    38  
    39  	m, err := NewResourceStatsMetrics()
    40  	if err != nil {
    41  		return nil, err
    42  	}
    43  	r.metrics = m
    44  	r.ApplyOptions(opts...)
    45  	if r.opts.checkInterval <= 0 {
    46  		r.opts.checkInterval = DefaultCheckInterval
    47  	}
    48  
    49  	return r, nil
    50  }
    51  
    52  // Run will initialize the backend. It must not block, but may run go routines in the background.
    53  func (s *ResourceStatsService) Run(ctx context.Context) error {
    54  	logger := s.getLogger()
    55  	logger.Infoln("ResourceStatsService Run")
    56  	if s.inShutdown.Load() {
    57  		logger.Infoln("ResourceStatsService Shutdown")
    58  		return fmt.Errorf("server closed")
    59  	}
    60  	go func() {
    61  		errors.HandleError(s.Serve(ctx))
    62  	}()
    63  	return nil
    64  }
    65  
    66  func (s *ResourceStatsService) getLogger() *logrus.Entry {
    67  	return logrus.WithField("module", "ResourceStatsService")
    68  }
    69  
    70  // Serve ...
    71  func (s *ResourceStatsService) Serve(ctx context.Context) error {
    72  	logger := s.getLogger()
    73  	logger.Infoln("ResourceStats Serve")
    74  
    75  	if s.inShutdown.Load() {
    76  		logger.Infoln("ResourceStats Shutdown")
    77  		return fmt.Errorf("server closed")
    78  	}
    79  
    80  	defer s.inShutdown.Store(true)
    81  	ctx, cancel := context.WithCancel(ctx)
    82  	defer cancel()
    83  	s.mu.Lock()
    84  	s.cancel = cancel
    85  	s.mu.Unlock()
    86  
    87  	time_.UntilWithContxt(ctx, func(ctx context.Context) error {
    88  		total, avaiable, usage := s.metrics.ReportMetric(ctx)
    89  		if s.opts.memoryCallBack != nil {
    90  			s.opts.memoryCallBack(uint64(total), uint64(avaiable), usage)
    91  		}
    92  		return nil
    93  	}, s.opts.checkInterval)
    94  	if err := ctx.Err(); err != nil {
    95  		logger.WithError(err).Errorf("stopped checking")
    96  		return err
    97  	}
    98  	logger.Info("stopped checking")
    99  	return nil
   100  }
   101  
   102  // Shutdown ...
   103  func (s *ResourceStatsService) Shutdown() {
   104  	s.inShutdown.Store(true)
   105  	s.mu.Lock()
   106  	defer s.mu.Unlock()
   107  	if s.cancel != nil {
   108  		s.cancel()
   109  	}
   110  }