app

package
Version: v0.27.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 3, 2021 License: Apache-2.0 Imports: 93 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrDBRequired = validation.NewFieldError("db-url", "is required")

ErrDBRequired is returned when the DB URL is unset.

View Source
var ErrLockerShutdown = errors.New("context locker is already shutdown")

ErrLockerShutdown is returned when attempting to aquire a lock after being shutdown.

View Source
var RootCmd = &cobra.Command{
	Use:   "goalert",
	Short: "Alerting platform.",
	RunE: func(cmd *cobra.Command, args []string) error {

		if viper.GetBool("json") {
			log.EnableJSON()
		}
		if viper.GetBool("verbose") {
			log.EnableVerbose()
		}
		if viper.GetBool("log-errors-only") {
			log.ErrorsOnly()
		}

		err := viper.ReadInConfig()

		if err != nil && !isCfgNotFound(err) {
			return errors.Wrap(err, "read config")
		}

		err = initPromServer()
		if err != nil {
			return err
		}

		ctx := context.Background()
		cfg, err := getConfig()
		if err != nil {
			return err
		}
		exporters, err := configTracing(ctx, cfg)
		if err != nil {
			return errors.Wrap(err, "config tracing")
		}

		defer func() {
			// flush exporters
			type flusher interface {
				Flush()
			}
			for _, e := range exporters {
				if f, ok := e.(flusher); ok {
					f.Flush()
				}
			}
		}()

		wrappedDriver := sqltrace.WrapDriver(&stdlib.Driver{}, &sqltrace.WrapOptions{Query: true})

		u, err := url.Parse(cfg.DBURL)
		if err != nil {
			return errors.Wrap(err, "parse old URL")
		}
		q := u.Query()
		if cfg.DBURLNext != "" {
			q.Set("application_name", fmt.Sprintf("GoAlert %s (S/O Mode)", version.GitVersion()))
		} else {
			q.Set("application_name", fmt.Sprintf("GoAlert %s", version.GitVersion()))
		}
		q.Set("enable_seqscan", "off")
		u.RawQuery = q.Encode()
		cfg.DBURL = u.String()

		if cfg.APIOnly {
			err = migrate.VerifyAll(log.EnableDebug(ctx), cfg.DBURL)
			if err != nil {
				return errors.Wrap(err, "verify migrations")
			}
		} else {
			s := time.Now()
			n, err := migrate.ApplyAll(log.EnableDebug(ctx), cfg.DBURL)
			if err != nil {
				return errors.Wrap(err, "apply migrations")
			}
			if n > 0 {
				log.Logf(ctx, "Applied %d migrations in %s.", n, time.Since(s))
			}
		}

		dbc, err := wrappedDriver.OpenConnector(cfg.DBURL)
		if err != nil {
			return errors.Wrap(err, "connect to postgres")
		}
		var db *sql.DB
		var h *switchover.Handler
		if cfg.DBURLNext != "" {
			u, err := url.Parse(cfg.DBURLNext)
			if err != nil {
				return errors.Wrap(err, "parse next URL")
			}
			q := u.Query()
			q.Set("application_name", fmt.Sprintf("GoAlert %s (S/O Mode)", version.GitVersion()))
			q.Set("enable_seqscan", "off")
			u.RawQuery = q.Encode()
			cfg.DBURLNext = u.String()

			dbcNext, err := wrappedDriver.OpenConnector(cfg.DBURLNext)
			if err != nil {
				return errors.Wrap(err, "connect to postres (next)")
			}
			h, err = switchover.NewHandler(ctx, dbc, dbcNext, cfg.DBURL, cfg.DBURLNext)
			if err != nil {
				return errors.Wrap(err, "init changeover handler")
			}
			db = h.DB()
		} else {
			db = sql.OpenDB(dbc)
		}

		app, err := NewApp(cfg, db)
		if err != nil {
			return errors.Wrap(err, "init app")
		}
		if h != nil {
			h.SetApp(app)
		}

		go handleShutdown(ctx, func(ctx context.Context) error {
			if h != nil {
				h.Abort()
			}
			return app.Shutdown(ctx)
		})

		trigCh := make(chan os.Signal, 1)
		signal.Notify(trigCh, triggerSignals...)
		go func() {
			for range trigCh {
				app.Trigger()
			}
		}()

		return errors.Wrap(app.Run(ctx), "run app")
	},
}

RootCmd is the configuration for running the app binary.

Functions

This section is empty.

Types

type App

type App struct {
	Engine *engine.Engine

	AuthHandler *auth.Handler

	ConfigStore *config.Store

	AlertStore    alert.Store
	AlertLogStore alertlog.Store

	UserStore             user.Store
	ContactMethodStore    contactmethod.Store
	NotificationRuleStore notificationrule.Store
	FavoriteStore         favorite.Store

	ServiceStore        service.Store
	EscalationStore     escalation.Store
	IntegrationKeyStore integrationkey.Store
	ScheduleRuleStore   rule.Store
	NotificationStore   notification.Store
	ScheduleStore       *schedule.Store
	RotationStore       rotation.Store

	CalSubStore    *calendarsubscription.Store
	OverrideStore  override.Store
	Resolver       resolver.Resolver
	LimitStore     *limit.Store
	HeartbeatStore heartbeat.Store

	OAuthKeyring   keyring.Keyring
	SessionKeyring keyring.Keyring
	APIKeyring     keyring.Keyring

	NonceStore    nonce.Store
	LabelStore    label.Store
	OnCallStore   oncall.Store
	NCStore       notificationchannel.Store
	TimeZoneStore *timezone.Store
	NoticeStore   *notice.Store
	// contains filtered or unexported fields
}

App represents an instance of the GoAlert application.

func NewApp

func NewApp(c Config, db *sql.DB) (*App, error)

NewApp constructs a new App and binds the listening socket.

func (*App) ActiveRequests

func (a *App) ActiveRequests() int

ActiveRequests returns the current number of active requests, not including pending ones during pause.

func (*App) DB

func (a *App) DB() *sql.DB

DB returns the sql.DB instance used by the application.

func (*App) Pause

func (app *App) Pause(ctx context.Context) error

func (*App) Resume

func (app *App) Resume()

func (*App) Run

func (app *App) Run(ctx context.Context) error

Run will start the application and start serving traffic.

func (*App) Shutdown

func (app *App) Shutdown(ctx context.Context) error

Shutdown will cause the App to begin a graceful shutdown, using the provided context for any cleanup operations.

func (*App) Status

func (a *App) Status() lifecycle.Status

Status returns the current lifecycle status of the App.

func (*App) Trigger

func (app *App) Trigger()

Trigger will start a processing cycle (normally ever ~5s)

func (*App) URL

func (a *App) URL() string

URL returns the non-TLS listener URL of the application.

func (*App) WaitForStartup

func (a *App) WaitForStartup(ctx context.Context) error

WaitForStartup will wait until the startup sequence is completed or the context is expired.

type Config

type Config struct {
	ListenAddr  string
	Verbose     bool
	JSON        bool
	LogRequests bool
	APIOnly     bool

	TLSListenAddr string
	TLSConfig     *tls.Config

	HTTPPrefix string

	DBMaxOpen int
	DBMaxIdle int

	MaxReqBodyBytes   int64
	MaxReqHeaderBytes int

	DisableHTTPSRedirect bool

	TwilioBaseURL string
	SlackBaseURL  string

	DBURL     string
	DBURLNext string

	JaegerEndpoint      string
	JaegerAgentEndpoint string

	StackdriverProjectID string

	TracingClusterName   string
	TracingPodNamespace  string
	TracingPodName       string
	TracingContainerName string
	TracingNodeName      string

	KubernetesCooldown time.Duration
	StatusAddr         string

	LogTraces        bool
	TraceProbability float64

	EncryptionKeys keyring.Keys

	RegionName string

	StubNotifiers bool

	UIURL string

	// InitialConfig will be pushed into the config store
	// if specified before the engine is started.
	InitialConfig *config.Config
}

func Defaults

func Defaults() Config

Defaults returns the default app config.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to