Exemple #1
0
func main() {
	// Arguments
	fileName := flag.String("c", "config.json", "config file")
	debug := flag.Bool("d", false, "debug mode")
	vers := flag.Bool("v", false, "version")
	flag.Parse()
	// Version
	if *vers {
		fmt.Fprintln(os.Stdout, version.Version)
		os.Exit(1)
	}
	// Logging
	log.SetName("banshee")
	if *debug {
		log.SetLevel(log.DEBUG)
	}
	log.Debug("using %s, max %d cpu", runtime.Version(), runtime.GOMAXPROCS(-1))
	// Config
	cfg := config.New()
	if flag.NFlag() == 0 || (flag.NFlag() == 1 && *debug == true) {
		log.Warn("no config file specified, using default..")
	} else {
		err := cfg.UpdateWithJSONFile(*fileName)
		if err != nil {
			log.Fatal("failed to load %s, %s", *fileName, err)
		}
	}
	// Storage
	options := &storage.Options{
		NumGrid: cfg.Period[0],
		GridLen: cfg.Period[1],
	}
	db, err := storage.Open(cfg.Storage.Path, options)
	if err != nil {
		log.Fatal("failed to open %s: %v", cfg.Storage.Path, err)
	}
	// Cleaner
	cleaner := cleaner.New(db, cfg.Period[0]*cfg.Period[1])
	go cleaner.Start()
	// Filter
	filter := filter.New()
	filter.Init(db)
	// Alerter
	alerter := alerter.New(cfg, db, filter)
	alerter.Start()
	// Webapp
	go webapp.Start(cfg, db)
	// Detector
	detector := detector.New(cfg, db, filter)
	detector.Out(alerter.In)
	detector.Start()
}
Exemple #2
0
// Migrate projects.
//
//	1. Fetch all projects from belldb.
//	2. Create the project into bansheedb.
//	3. Create the rules for each project.
//
func migrateProjects() {
	var projs []Project
	// Fetch all projects from belldb.
	if err := bellDB.Find(&projs).Error; err != nil {
		log.Fatal("fetch all projects from %s: %v", *bellDBFileName, err)
	}
	for _, proj := range projs {
		// Create banshee project.
		if err := models.ValidateProjectName(proj.Name); err != nil {
			log.Warn("project %s: %v, skipping..", proj.Name, err)
			continue
		}
		p := &models.Project{Name: proj.Name}
		if err := bansheeDB.Create(p).Error; err != nil {
			sqliteErr, ok := err.(sqlite3.Error)
			if ok && sqliteErr.ExtendedCode == sqlite3.ErrConstraintUnique {
				log.Warn("project %s already in %s, skipping..", p.Name, *bansheeDBFileName)
			} else {
				log.Fatal("cannot create project %s: %v", p.Name, err)
			}
		}
		// Fetch its rules from belldb.
		var rules []Rule
		if err := bellDB.Model(proj).Related(&rules).Error; err != nil {
			log.Fatal("cannot fetch rules for %s: %v", p.Name, err)
		}
		for _, rule := range rules {
			// Create banshee rule.
			if err := models.ValidateRulePattern(rule.Pattern); err != nil {
				log.Warn("rule %s: %v, belongs to %s, skippig..", rule.Pattern, err, proj.Name)
				continue
			}
			r := &models.Rule{
				Pattern:   rule.Pattern,
				ProjectID: p.ID,
				TrendUp:   rule.Up,
				TrendDown: rule.Down,
				// Important: max and min for bell is reversed with banshee's.
				ThresholdMax: rule.Min,
				ThresholdMin: rule.Max,
			}
			if err := bansheeDB.Create(r).Error; err != nil {
				sqliteErr, ok := err.(sqlite3.Error)
				if ok && sqliteErr.ExtendedCode == sqlite3.ErrConstraintUnique {
					log.Warn("rule %s already in %s, skipping..", r.Pattern, *bansheeDBFileName)
				} else {
					log.Fatal("cannot create rule %s: %v", r.Pattern, err)
				}
			}
		}
	}
}
Exemple #3
0
// Start detector.
func (d *Detector) Start() {
	addr := fmt.Sprintf("0.0.0.0:%d", d.cfg.Detector.Port)
	ln, err := net.Listen("tcp", addr)
	if err != nil {
		log.Fatal("failed to bind tcp://%s: %v", addr, err)
	}
	log.Info("detector is listening on tcp://%s..", addr)
	for {
		conn, err := ln.Accept()
		if err != nil {
			log.Fatal("accept conn: %v", err)
		}
		go d.handle(conn)
	}
}
Exemple #4
0
func initConfig() {
	// Config parsing.
	if flag.NFlag() == 0 || (flag.NFlag() == 1 && *debug) {
		// Case ./program [-d]
		log.Warn("no config specified, using default..")
	} else {
		// Update config.
		err := cfg.UpdateWithJSONFile(*fileName)
		if err != nil {
			log.Fatal("failed to load %s, %s", *fileName, err)
		}
	}
	// Config validation.
	err := cfg.Validate()
	if err != nil {
		log.Fatal("config: %s", err)
	}
}
Exemple #5
0
// Init.
//
//	1. Parse arguments.
//	2. Init db handles.
//	3. Auto migrate schema.
//
func init() {
	flag.Parse()
	// Bell DB
	if db, err := gorm.Open("sqlite3", *bellDBFileName); err != nil {
		log.Fatal("%s: %v", *bellDBFileName, err)
	} else {
		bellDB = &db
		bellDB.LogMode(false)
	}
	// Banshee DB
	if db, err := gorm.Open("sqlite3", *bansheeDBFileName); err != nil {
		log.Fatal("%s:%v", *bansheeDBFileName, err)
	} else {
		bansheeDB = &db
		bansheeDB.LogMode(false)
	}
	if err := bansheeDB.AutoMigrate(&models.Project{}, &models.Rule{}, &models.User{}).Error; err != nil {
		log.Fatal("failed to migrate schema for %s: %v", *bansheeDBFileName, err)
	}
}
Exemple #6
0
func initDB() {
	// Rely on config.
	if cfg == nil {
		panic(errors.New("db require config"))
	}
	path := cfg.Storage.Path
	var err error
	db, err = storage.Open(path)
	if err != nil {
		log.Fatal("failed to open %s: %v", path, err)
	}
}
Exemple #7
0
// Start http server.
func Start(c *config.Config, d *storage.DB, f *filter.Filter) {
	// Init globals.
	cfg = c
	db = d
	flt = f
	// Auth
	auth := newAuthHandler(cfg.Webapp.Auth[0], cfg.Webapp.Auth[1])
	// Routes
	router := httprouter.New()
	// Api
	router.GET("/api/config", auth.handler(getConfig))
	router.GET("/api/interval", getInterval)
	router.GET("/api/privateDocUrl", getPrivateDocURL)
	router.GET("/api/graphiteUrl", getGraphiteURL)
	router.GET("/api/language", getLanguage)
	router.GET("/api/projects", getProjects)
	router.GET("/api/project/:id", getProject)
	router.POST("/api/project", auth.handler(createProject))
	router.PATCH("/api/project/:id", auth.handler(updateProject))
	router.DELETE("/api/project/:id", auth.handler(deleteProject))
	router.GET("/api/project/:id/rules", auth.handler(getProjectRules))
	router.GET("/api/project/:id/users", auth.handler(getProjectUsers))
	router.POST("/api/project/:id/user", auth.handler(addProjectUser))
	router.DELETE("/api/project/:id/user/:user_id", auth.handler(deleteProjectUser))
	router.GET("/api/project/:id/events", auth.handler(getEventsByProjectID))
	router.GET("/api/users", auth.handler(getUsers))
	router.GET("/api/user/:id", auth.handler(getUser))
	router.POST("/api/user", auth.handler(createUser))
	router.DELETE("/api/user/:id", auth.handler(deleteUser))
	router.PATCH("/api/user/:id", auth.handler(updateUser))
	router.GET("/api/user/:id/projects", auth.handler(getUserProjects))
	router.POST("/api/project/:id/rule", auth.handler(createRule))
	router.DELETE("/api/rule/:id", auth.handler(deleteRule))
	router.PATCH("/api/rule/:id", auth.handler(editRule))
	router.GET("/api/metric/rules/:name", getMetricRules)
	router.GET("/api/metric/indexes", getMetricIndexes)
	router.GET("/api/metric/data", getMetrics)
	router.GET("/api/info", getInfo)
	router.GET("/api/version", getVersion)
	// Static
	router.NotFound = newStaticHandler(http.Dir(cfg.Webapp.Static), auth)
	// Serve
	addr := fmt.Sprintf("0.0.0.0:%d", cfg.Webapp.Port)
	log.Infof("webapp is listening and serving on %s..", addr)
	log.Fatal(http.ListenAndServe(addr, router))
}
Exemple #8
0
// Start the tcp server.
func (d *Detector) Start() {
	// Listen
	addr := fmt.Sprintf("0.0.0.0:%d", d.cfg.Detector.Port)
	ln, err := net.Listen("tcp", addr)
	if err != nil {
		log.Fatal("listen: %v", err)
	}
	log.Info("detector is listening on %s..", addr)
	// Accept
	for {
		conn, err := ln.Accept()
		if err != nil {
			log.Error("cannot accept conn: %v, skipping..", err)
			continue
		}
		go d.handle(conn)
	}
}
Exemple #9
0
// Migrate users.
//
//	1. Fetch all users from belldb.
//	2. Create the users into bansheedb.
//	3. Establish the relationships between project and user.
//
func migrateUsers() {
	var users []Receiver
	// Fetch all users from belldb.
	if err := bellDB.Find(&users).Error; err != nil {
		log.Fatal("fetch all users from %s: %v", *bellDBFileName, err)
	}
	for _, user := range users {
		// Create banshee user.
		err := models.ValidateUserName(user.Name)
		if err == nil {
			err = models.ValidateUserEmail(user.Email)
		}
		if err == nil {
			err = models.ValidateUserPhone(user.Phone)
		}
		if err != nil {
			log.Warn("user %s: %v, skipping..", user.Name, err)
		}
		u := &models.User{
			Name:        user.Name,
			Email:       user.Email,
			Phone:       user.Phone,
			EnableEmail: user.EnableEmail,
			EnablePhone: user.EnablePhone,
			Universal:   user.Universal,
		}
		if err := bansheeDB.Create(u).Error; err != nil {
			sqliteErr, ok := err.(sqlite3.Error)
			if ok && sqliteErr.ExtendedCode == sqlite3.ErrConstraintUnique {
				log.Warn("user %s already in %s, skipping..", u.Name, *bansheeDBFileName)
			} else {
				log.Fatal("cannot create user %s: %v", u.Name, err)
			}
		}
		// Establish relationship to project.
		if user.Universal {
			continue
		}
		// Get all relationships for this user.
		var relations []ReceiverProject
		if err := bellDB.Where("ReceiverId = ?", user.ID).Find(&relations).Error; err != nil {
			log.Fatal("cannot fetch user-project relations for user %s: %v", user.Name, err)
		}
		for _, relation := range relations {
			var proj Project
			if err := bellDB.First(&proj, relation.ProjectID).Error; err != nil {
				if err == gorm.RecordNotFound {
					log.Warn("project %d not found for user %s, skipping..", relation.ProjectID, user.Name)
					continue
				}
				log.Fatal("cannot get project %d for user %s", relation.ProjectID, user.Name)
			}
			p := &models.Project{}
			if err := bansheeDB.Where("name = ?", proj.Name).First(p).Error; err != nil {
				if err == gorm.RecordNotFound {
					log.Warn("project %s not found in %s, skipping..", proj.Name, *bansheeDBFileName)
					continue
				}
				log.Fatal("cannot get project %s in %s", proj.Name, *bansheeDBFileName)
			}
			if err := bansheeDB.Model(p).Association("Users").Append(u).Error; err != nil {
				if err == gorm.RecordNotFound {
					log.Warn("record not found: %v", err)
					continue
				}
				log.Fatal("cannot append user %s to project %s:%v", u.Name, p.Name, err)
			}
		}
	}
}