예제 #1
0
// handle a new connection:
// Steps:
//	1. Read input from connection line by line.
//	2. Parse each line into a metric.
//	3. Validate the metric
//	4. Process the metric.
func (d *Detector) handle(conn net.Conn) {
	addr := conn.RemoteAddr()
	health.IncrNumClients(1)
	defer health.DecrNumClients(1)
	log.Infof("conn %s established", addr)
	scanner := bufio.NewScanner(conn)
	for scanner.Scan() { // Read line by line.
		if err := scanner.Err(); err != nil { // Close on read error.
			log.Errorf("read error: %v, closing conn..", err)
			break
		}
		line := scanner.Text()
		m, err := parseMetric(line) // Parse
		if err != nil {
			log.Errorf("parse error: %v, skipping..", err)
			continue
		}
		if err = m.Validate(); err != nil {
			log.Errorf("invalid metric: %v, skipping..", err)
			return
		}
		d.process(m, true)
	}
	conn.Close()
	log.Infof("conn %s disconnected", addr)
}
예제 #2
0
// Start workers to wait for events.
func (al *Alerter) Start() {
	log.Infof("start %d alerter workers..", al.cfg.Alerter.Workers)
	for i := 0; i < al.cfg.Alerter.Workers; i++ {
		go al.work()
	}
	al.initAlerterNumsReseter()
}
예제 #3
0
// work waits for events to alert.
func (al *Alerter) work() {
	for {
		ev := <-al.In
		ew := models.NewWrapperOfEvent(ev) // Avoid locks
		if al.checkAlertAt(ew.Metric) {    // Check alert interval
			continue
		}
		if al.checkOneDayAlerts(ew.Metric) { // Check one day limit
			continue
		}
		// Avoid noises by issuing alerts only when same alert has occurred
		// predefined times.
		if al.checkAlertCount(ew.Metric) {
			al.setAlertRecord(ew.Metric)
			log.Warnf("Not enough alerts with in `AlertCheckInterval` time skipping..: %v", ew.Metric.Name)
			continue
		}
		al.setAlertRecord(ew.Metric)
		al.incrAlertNum(ew.Metric)
		// Store event
		if err := al.storeEvent(ev); err != nil {
			log.Warnf("failed to store event:%v, skipping..", err)
			continue
		}
		// Do alert.
		var err error
		if ew.Project, err = al.getProjByRule(ew.Rule); err != nil {
			continue
		}
		if al.shoudProjBeSilent(ew.Project) {
			continue
		}
		var users []models.User
		if users, err = al.getUsersByProj(ew.Project); err != nil {
			continue
		}
		for _, user := range users {
			ew.User = &user
			if ew.Rule.Level < user.RuleLevel {
				continue
			}
			if len(al.cfg.Alerter.Command) == 0 {
				log.Warnf("alert command not configured")
				continue
			}
			if err = al.execCommand(ew); err != nil { // Execute command
				log.Errorf("exec %s: %v", al.cfg.Alerter.Command, err)
				continue
			}
			log.Infof("send to %s with %s ok", user.Name, ew.Metric.Name)
		}
		if len(users) != 0 {
			al.setAlertAt(ew.Metric)
			health.IncrNumAlertingEvents(1)
		}
	}
}
예제 #4
0
// Start the tcp server.
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.Fatalf("listen: %v", err)
	}
	log.Infof("detector is listening on %s", addr)
	go d.startIdleTracking()
	for {
		conn, err := ln.Accept()
		if err != nil {
			log.Errorf("cannot accept conn: %v, skipping..", err)
			continue
		}
		go d.handle(conn)
	}
}
예제 #5
0
파일: server.go 프로젝트: yujinqiu/banshee
// 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))
}
예제 #6
0
// createStorage creates a storage for given stamp.
// Dose nothing if the stamp is not large enough.
func (db *DB) createStorage(stamp uint32) error {
	id := stamp / db.opts.Period
	if len(db.pool) > 0 && id <= db.pool[len(db.pool)-1].id {
		// stamp is not large enough.
		return nil
	}
	baseName := strconv.FormatUint(uint64(id), 10)
	fileName := path.Join(db.name, baseName)
	ldb, err := leveldb.OpenFile(fileName, nil)
	if err != nil {
		return err
	}
	s := &storage{db: ldb, id: id}
	db.pool = append(db.pool, s)
	log.Infof("storage %d created", id)
	return nil
}
예제 #7
0
파일: db.go 프로젝트: yujinqiu/banshee
// createStorage creates a storage for given stamp.
// Dose nothing if the stamp is not large enough.
func (db *DB) createStorage(stamp uint32) error {
	id := stamp / db.opts.Period
	if len(db.pool) > 0 && id <= db.pool[len(db.pool)-1].id {
		// stamp is not large enough.
		return nil
	}
	baseName := strconv.FormatUint(uint64(id), 10)
	fileName := path.Join(db.name, baseName)
	gdb, err := gorm.Open(dialect, fileName)
	if err != nil {
		return err
	}
	s := &storage{db: &gdb, id: id}
	if err = s.migrate(); err != nil { // DoNot forget
		return err
	}
	db.pool = append(db.pool, s)
	log.Infof("storage %d created", id)
	return nil
}
예제 #8
0
파일: db.go 프로젝트: yujinqiu/banshee
// expireStorage expires storages.
// Dose nothing if the pool needs no expiration.
func (db *DB) expireStorages() error {
	if len(db.pool) == 0 {
		return nil
	}
	id := db.pool[len(db.pool)-1].id - db.opts.Expiration/db.opts.Period
	pool := db.pool
	for i, s := range db.pool {
		if s.id < id {
			if err := s.close(); err != nil {
				return err
			}
			baseName := strconv.FormatUint(uint64(s.id), 10)
			fileName := path.Join(db.name, baseName)
			if err := os.RemoveAll(fileName); err != nil {
				return err
			}
			pool = db.pool[i+1:]
			log.Infof("storage %d expired", s.id)
		}
	}
	db.pool = pool
	return nil
}