mirror of
https://github.com/prymitive/karma
synced 2026-05-09 03:36:44 +00:00
Only HOST & PORT env variables used by gin internally were really used, pass resulting config to gin so we match documentation, and log it on startup
161 lines
4.0 KiB
Go
161 lines
4.0 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"html/template"
|
|
"path"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/cloudflare/unsee/internal/alertmanager"
|
|
"github.com/cloudflare/unsee/internal/config"
|
|
"github.com/cloudflare/unsee/internal/models"
|
|
"github.com/cloudflare/unsee/internal/transform"
|
|
|
|
"github.com/DeanThompson/ginpprof"
|
|
"github.com/gin-contrib/gzip"
|
|
"github.com/gin-contrib/static"
|
|
"github.com/gin-gonic/contrib/sentry"
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/patrickmn/go-cache"
|
|
|
|
raven "github.com/getsentry/raven-go"
|
|
ginprometheus "github.com/mcuadros/go-gin-prometheus"
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
var (
|
|
version = "dev"
|
|
|
|
// ticker is a timer used by background loop that will keep pulling
|
|
// data from Alertmanager
|
|
ticker *time.Ticker
|
|
|
|
// apiCache will be used to keep short lived copy of JSON reponses generated for the UI
|
|
// If there are requests with the same filter we should respond from cache
|
|
// rather than do all the filtering every time
|
|
apiCache *cache.Cache
|
|
)
|
|
|
|
func getViewURL(sub string) string {
|
|
u := path.Join(config.Config.Listen.Prefix, sub)
|
|
if strings.HasSuffix(sub, "/") {
|
|
// if sub path had trailing slash then add it here, since path.Join will
|
|
// skip it
|
|
return u + "/"
|
|
}
|
|
return u
|
|
}
|
|
|
|
func setupRouter(router *gin.Engine) {
|
|
router.Use(gzip.Gzip(gzip.DefaultCompression))
|
|
router.Use(static.Serve(getViewURL("/static"), newBinaryFileSystem("static")))
|
|
|
|
router.GET(getViewURL("/favicon.ico"), favicon)
|
|
router.GET(getViewURL("/"), index)
|
|
router.GET(getViewURL("/help"), help)
|
|
router.GET(getViewURL("/alerts.json"), alerts)
|
|
router.GET(getViewURL("/autocomplete.json"), autocomplete)
|
|
}
|
|
|
|
func setupUpstreams() {
|
|
for _, s := range config.Config.Alertmanager.Servers {
|
|
err := alertmanager.NewAlertmanager(s.Name, s.URI, s.Timeout)
|
|
if err != nil {
|
|
log.Fatalf("Failed to configure Alertmanager '%s' with URI '%s': %s", s.Name, s.URI, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func setupLogger() {
|
|
switch config.Config.Log.Level {
|
|
case "debug":
|
|
log.SetLevel(log.DebugLevel)
|
|
case "info":
|
|
log.SetLevel(log.InfoLevel)
|
|
case "warning":
|
|
log.SetLevel(log.WarnLevel)
|
|
case "error":
|
|
log.SetLevel(log.ErrorLevel)
|
|
case "fatal":
|
|
log.SetLevel(log.FatalLevel)
|
|
case "panic":
|
|
log.SetLevel(log.PanicLevel)
|
|
default:
|
|
log.Fatalf("Unknown log level '%s'", config.Config.Log.Level)
|
|
}
|
|
}
|
|
|
|
func main() {
|
|
config.Config.Read()
|
|
setupLogger()
|
|
|
|
// timer duration cannot be zero second or a negative one
|
|
if config.Config.Alertmanager.Interval <= time.Second*0 {
|
|
log.Fatalf("Invalid AlertmanagerTTL value '%v'", config.Config.Alertmanager.Interval)
|
|
}
|
|
|
|
log.Infof("Version: %s", version)
|
|
if config.Config.Log.Config {
|
|
config.Config.LogValues()
|
|
}
|
|
|
|
jiraRules := []models.JiraRule{}
|
|
for _, rule := range config.Config.JIRA {
|
|
jiraRules = append(jiraRules, models.JiraRule{Regex: rule.Regex, URI: rule.URI})
|
|
}
|
|
transform.ParseRules(jiraRules)
|
|
|
|
apiCache = cache.New(cache.NoExpiration, 10*time.Second)
|
|
|
|
setupUpstreams()
|
|
|
|
if len(alertmanager.GetAlertmanagers()) == 0 {
|
|
log.Fatal("No valid Alertmanager URIs defined")
|
|
}
|
|
|
|
// before we start try to fetch data from Alertmanager
|
|
log.Info("Initial Alertmanager query")
|
|
pullFromAlertmanager()
|
|
log.Info("Done, starting HTTP server")
|
|
|
|
// background loop that will fetch updates from Alertmanager
|
|
ticker = time.NewTicker(config.Config.Alertmanager.Interval)
|
|
go Tick()
|
|
|
|
switch config.Config.Debug {
|
|
case true:
|
|
gin.SetMode(gin.DebugMode)
|
|
case false:
|
|
gin.SetMode(gin.ReleaseMode)
|
|
}
|
|
|
|
router := gin.New()
|
|
|
|
var t *template.Template
|
|
t = loadTemplates(t, "templates")
|
|
t = loadTemplates(t, "static/dist/templates")
|
|
router.SetHTMLTemplate(t)
|
|
|
|
prom := ginprometheus.NewPrometheus("gin")
|
|
prom.MetricsPath = getViewURL("/metrics")
|
|
prom.Use(router)
|
|
|
|
if config.Config.Debug {
|
|
ginpprof.Wrapper(router)
|
|
}
|
|
|
|
if config.Config.Sentry.Public != "" {
|
|
raven.SetRelease(version)
|
|
router.Use(sentry.Recovery(raven.DefaultClient, false))
|
|
}
|
|
|
|
setupRouter(router)
|
|
listen := fmt.Sprintf("%s:%d", config.Config.Listen.Address, config.Config.Listen.Port)
|
|
log.Infof("Listening on %s", listen)
|
|
err := router.Run(listen)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|