From 86b546c21da687caff861c6925db5d68a565a889 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Fri, 30 Sep 2016 08:36:20 +0200 Subject: [PATCH] refactor(main): refactoring main grafana server / startup code --- pkg/cmd/grafana-server/main.go | 66 ++----------- pkg/cmd/grafana-server/server.go | 129 +++++++++++++++++++++++++ pkg/{core/core.go => models/server.go} | 6 +- 3 files changed, 138 insertions(+), 63 deletions(-) create mode 100644 pkg/cmd/grafana-server/server.go rename pkg/{core/core.go => models/server.go} (54%) diff --git a/pkg/cmd/grafana-server/main.go b/pkg/cmd/grafana-server/main.go index 877fc573169..ad236edf545 100644 --- a/pkg/cmd/grafana-server/main.go +++ b/pkg/cmd/grafana-server/main.go @@ -1,7 +1,6 @@ package main import ( - "context" "flag" "fmt" "io/ioutil" @@ -13,21 +12,11 @@ import ( "syscall" "time" - "golang.org/x/sync/errgroup" - "github.com/grafana/grafana/pkg/log" - "github.com/grafana/grafana/pkg/login" - "github.com/grafana/grafana/pkg/metrics" - "github.com/grafana/grafana/pkg/plugins" - "github.com/grafana/grafana/pkg/services/cleanup" - "github.com/grafana/grafana/pkg/services/eventpublisher" - "github.com/grafana/grafana/pkg/services/notifications" - "github.com/grafana/grafana/pkg/services/search" + "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/setting" - "github.com/grafana/grafana/pkg/social" - "github.com/grafana/grafana/pkg/services/alerting" _ "github.com/grafana/grafana/pkg/services/alerting/conditions" _ "github.com/grafana/grafana/pkg/services/alerting/notifiers" _ "github.com/grafana/grafana/pkg/tsdb/graphite" @@ -66,41 +55,8 @@ func main() { setting.BuildCommit = commit setting.BuildStamp = buildstampInt64 - appContext, shutdownFn := context.WithCancel(context.Background()) - grafanaGroup, appContext := errgroup.WithContext(appContext) - - go listenToSystemSignals(shutdownFn, grafanaGroup) - - flag.Parse() - writePIDFile() - - initRuntime() - initSql() - metrics.Init() - search.Init() - login.Init() - social.NewOAuthService() - eventpublisher.Init() - plugins.Init() - - // init alerting - if setting.AlertingEnabled { - engine := alerting.NewEngine() - grafanaGroup.Go(func() error { return engine.Run(appContext) }) - } - - // cleanup service - cleanUpService := cleanup.NewCleanUpService() - grafanaGroup.Go(func() error { return cleanUpService.Run(appContext) }) - - if err := notifications.Init(); err != nil { - log.Fatal(3, "Notification service failed to initialize", err) - } - - exitCode := StartServer() - - grafanaGroup.Wait() - exitChan <- exitCode + server := NewGrafanaServer() + server.Start() } func initRuntime() { @@ -143,7 +99,7 @@ func writePIDFile() { } } -func listenToSystemSignals(cancel context.CancelFunc, grafanaGroup *errgroup.Group) { +func listenToSystemSignals(server models.GrafanaServer) { signalChan := make(chan os.Signal, 1) code := 0 @@ -151,18 +107,8 @@ func listenToSystemSignals(cancel context.CancelFunc, grafanaGroup *errgroup.Gro select { case sig := <-signalChan: - log.Info2("Received system signal. Shutting down", "signal", sig) + server.Shutdown(0, fmt.Sprintf("system signal=%s", sig)) case code = <-exitChan: - switch code { - case 0: - log.Info("Shutting down") - default: - log.Warn("Shutting down") - } + server.Shutdown(code, "startup error") } - - cancel() - grafanaGroup.Wait() - log.Close() - os.Exit(code) } diff --git a/pkg/cmd/grafana-server/server.go b/pkg/cmd/grafana-server/server.go new file mode 100644 index 00000000000..5ffdba5804f --- /dev/null +++ b/pkg/cmd/grafana-server/server.go @@ -0,0 +1,129 @@ +package main + +import ( + "context" + "fmt" + "net/http" + "os" + "time" + + "golang.org/x/sync/errgroup" + + "github.com/grafana/grafana/pkg/api" + "github.com/grafana/grafana/pkg/log" + "github.com/grafana/grafana/pkg/login" + "github.com/grafana/grafana/pkg/metrics" + "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/plugins" + "github.com/grafana/grafana/pkg/services/alerting" + "github.com/grafana/grafana/pkg/services/cleanup" + "github.com/grafana/grafana/pkg/services/eventpublisher" + "github.com/grafana/grafana/pkg/services/notifications" + "github.com/grafana/grafana/pkg/services/search" + "github.com/grafana/grafana/pkg/setting" + "github.com/grafana/grafana/pkg/social" +) + +func NewGrafanaServer() models.GrafanaServer { + rootCtx, shutdownFn := context.WithCancel(context.Background()) + childRoutines, childCtx := errgroup.WithContext(rootCtx) + + return &GrafanaServerImpl{ + context: childCtx, + shutdownFn: shutdownFn, + childRoutines: childRoutines, + log: log.New("server"), + } +} + +type GrafanaServerImpl struct { + context context.Context + shutdownFn context.CancelFunc + childRoutines *errgroup.Group + log log.Logger +} + +func (g *GrafanaServerImpl) Start() { + go listenToSystemSignals(g) + + writePIDFile() + initRuntime() + initSql() + metrics.Init() + search.Init() + login.Init() + social.NewOAuthService() + eventpublisher.Init() + plugins.Init() + + // init alerting + if setting.AlertingEnabled { + engine := alerting.NewEngine() + g.childRoutines.Go(func() error { return engine.Run(g.context) }) + } + + // cleanup service + cleanUpService := cleanup.NewCleanUpService() + g.childRoutines.Go(func() error { return cleanUpService.Run(g.context) }) + + if err := notifications.Init(); err != nil { + g.log.Error("Notification service failed to initialize", "erro", err) + g.Shutdown(1, "Startup failed") + return + } + + g.startHttpServer() +} + +func (g *GrafanaServerImpl) startHttpServer() { + logger = log.New("http.server") + + var err error + m := newMacaron() + api.Register(m) + + listenAddr := fmt.Sprintf("%s:%s", setting.HttpAddr, setting.HttpPort) + g.log.Info("Initializing HTTP Server", "address", listenAddr, "protocol", setting.Protocol, "subUrl", setting.AppSubUrl) + + switch setting.Protocol { + case setting.HTTP: + err = http.ListenAndServe(listenAddr, m) + case setting.HTTPS: + err = http.ListenAndServeTLS(listenAddr, setting.CertFile, setting.KeyFile, m) + default: + g.log.Error("Invalid protocol", "protocol", setting.Protocol) + g.Shutdown(1, "Startup failed") + } + + if err != nil { + g.log.Error("Fail to start server", "error", err) + g.Shutdown(1, "Startup failed") + return + } +} + +func (g *GrafanaServerImpl) Shutdown(code int, reason string) { + log.Info("Shutting down", "code", code, "reason", reason) + + g.shutdownFn() + err := g.childRoutines.Wait() + + log.Info("Shutting down completed", "error", err) + + log.Close() + os.Exit(code) +} + +// implement context.Context +func (g *GrafanaServerImpl) Deadline() (deadline time.Time, ok bool) { + return g.context.Deadline() +} +func (g *GrafanaServerImpl) Done() <-chan struct{} { + return g.context.Done() +} +func (g *GrafanaServerImpl) Err() error { + return g.context.Err() +} +func (g *GrafanaServerImpl) Value(key interface{}) interface{} { + return g.context.Value(key) +} diff --git a/pkg/core/core.go b/pkg/models/server.go similarity index 54% rename from pkg/core/core.go rename to pkg/models/server.go index e6eba5fbe41..876fc91dd01 100644 --- a/pkg/core/core.go +++ b/pkg/models/server.go @@ -1,10 +1,10 @@ -package core +package models import "context" type GrafanaServer interface { context.Context -} -type GrafanaServerImpl struct { + Start() + Shutdown(code int, reason string) }