Files
grafana/pkg/services/frontend/frontend_service.go

89 lines
2.3 KiB
Go

package frontend
import (
"context"
"net"
"net/http"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/grafana/dskit/services"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/services/licensing"
"github.com/grafana/grafana/pkg/setting"
)
type frontendService struct {
*services.BasicService
cfg *setting.Cfg
httpServ *http.Server
log log.Logger
errChan chan error
promGatherer prometheus.Gatherer
index *IndexProvider
}
func ProvideFrontendService(cfg *setting.Cfg, promGatherer prometheus.Gatherer, license licensing.Licensing) (*frontendService, error) {
index, err := NewIndexProvider(cfg, license)
if err != nil {
return nil, err
}
s := &frontendService{
cfg: cfg,
log: log.New("frontend-server"),
promGatherer: promGatherer,
index: index,
}
s.BasicService = services.NewBasicService(s.start, s.running, s.stop)
return s, nil
}
func (s *frontendService) start(ctx context.Context) error {
s.httpServ = s.newFrontendServer(ctx)
s.errChan = make(chan error)
go func() {
s.errChan <- s.httpServ.ListenAndServe()
}()
return nil
}
func (s *frontendService) running(ctx context.Context) error {
select {
case <-ctx.Done():
return nil
case err := <-s.errChan:
return err
}
}
func (s *frontendService) stop(failureReason error) error {
s.log.Info("stopping frontend server", "reason", failureReason)
if err := s.httpServ.Shutdown(context.Background()); err != nil {
s.log.Error("failed to shutdown frontend server", "error", err)
return err
}
return nil
}
func (s *frontendService) newFrontendServer(ctx context.Context) *http.Server {
s.log.Info("starting frontend server", "addr", ":"+s.cfg.HTTPPort)
router := http.NewServeMux()
router.Handle("/metrics", promhttp.HandlerFor(s.promGatherer, promhttp.HandlerOpts{EnableOpenMetrics: true}))
router.HandleFunc("/", s.index.HandleRequest)
server := &http.Server{
// 5s timeout for header reads to avoid Slowloris attacks (https://thetooth.io/blog/slowloris-attack/)
ReadHeaderTimeout: 5 * time.Second,
Addr: ":" + s.cfg.HTTPPort,
Handler: router,
BaseContext: func(_ net.Listener) context.Context { return ctx },
}
return server
}