github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/services/metrics/metrics.go (about)

     1  package metrics
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"net"
     8  	"net/http"
     9  	"sync/atomic"
    10  
    11  	"github.com/nspcc-dev/neo-go/pkg/config"
    12  	"go.uber.org/zap"
    13  )
    14  
    15  // Service serves metrics.
    16  type Service struct {
    17  	http        []*http.Server
    18  	config      config.BasicService
    19  	log         *zap.Logger
    20  	serviceType string
    21  	started     atomic.Bool
    22  }
    23  
    24  // NewService configures logger and returns new service instance.
    25  func NewService(name string, httpServers []*http.Server, cfg config.BasicService, log *zap.Logger) *Service {
    26  	return &Service{
    27  		http:        httpServers,
    28  		config:      cfg,
    29  		serviceType: name,
    30  		log:         log.With(zap.String("service", name)),
    31  	}
    32  }
    33  
    34  // Start runs http service with the exposed endpoint on the configured port.
    35  func (ms *Service) Start() error {
    36  	if ms.config.Enabled {
    37  		if !ms.started.CompareAndSwap(false, true) {
    38  			ms.log.Info("service already started")
    39  			return nil
    40  		}
    41  		for _, srv := range ms.http {
    42  			ms.log.Info("starting service", zap.String("endpoint", srv.Addr))
    43  
    44  			ln, err := net.Listen("tcp", srv.Addr)
    45  			if err != nil {
    46  				return fmt.Errorf("failed to listen on %s: %w", srv.Addr, err)
    47  			}
    48  			srv.Addr = ln.Addr().String() // set Addr to the actual address
    49  
    50  			go func(s *http.Server) {
    51  				err = s.Serve(ln)
    52  				if !errors.Is(err, http.ErrServerClosed) {
    53  					ms.log.Error("failed to start service", zap.String("endpoint", s.Addr), zap.Error(err))
    54  				}
    55  			}(srv)
    56  		}
    57  	} else {
    58  		ms.log.Info("service hasn't started since it's disabled")
    59  	}
    60  	return nil
    61  }
    62  
    63  // ShutDown stops the service.
    64  func (ms *Service) ShutDown() {
    65  	if !ms.config.Enabled {
    66  		return
    67  	}
    68  	if !ms.started.CompareAndSwap(true, false) {
    69  		return
    70  	}
    71  	for _, srv := range ms.http {
    72  		ms.log.Info("shutting down service", zap.String("endpoint", srv.Addr))
    73  		err := srv.Shutdown(context.Background())
    74  		if err != nil {
    75  			ms.log.Error("can't shut service down", zap.String("endpoint", srv.Addr), zap.Error(err))
    76  		}
    77  	}
    78  	_ = ms.log.Sync()
    79  }