Beispiel #1
0
func TestRuleTest(t *testing.T) {
	var rule *Rule
	// TrendUp
	rule = &Rule{TrendUp: true}
	assert.Ok(t, rule.Test(&Metric{}, &Index{Score: 1.2}, nil))
	assert.Ok(t, !rule.Test(&Metric{}, &Index{Score: 0.8}, nil))
	// TrendDown
	rule = &Rule{TrendDown: true}
	assert.Ok(t, rule.Test(&Metric{}, &Index{Score: -1.2}, nil))
	assert.Ok(t, !rule.Test(&Metric{}, &Index{Score: 1.2}, nil))
	// TrendUp And Value >= X
	rule = &Rule{TrendUp: true, ThresholdMax: 39}
	assert.Ok(t, rule.Test(&Metric{Value: 50}, &Index{Score: 1.3}, nil))
	assert.Ok(t, !rule.Test(&Metric{Value: 38}, &Index{Score: 1.5}, nil))
	assert.Ok(t, !rule.Test(&Metric{Value: 60}, &Index{Score: 0.9}, nil))
	// TrendDown And Value <= X
	rule = &Rule{TrendDown: true, ThresholdMin: 40}
	assert.Ok(t, rule.Test(&Metric{Value: 10}, &Index{Score: -1.2}, nil))
	assert.Ok(t, !rule.Test(&Metric{Value: 41}, &Index{Score: -1.2}, nil))
	assert.Ok(t, !rule.Test(&Metric{Value: 12}, &Index{Score: -0.2}, nil))
	// (TrendUp And Value >= X) Or TrendDown
	rule = &Rule{TrendUp: true, TrendDown: true, ThresholdMax: 90}
	assert.Ok(t, rule.Test(&Metric{Value: 100}, &Index{Score: 1.1}, nil))
	assert.Ok(t, rule.Test(&Metric{}, &Index{Score: -1.1}, nil))
	assert.Ok(t, !rule.Test(&Metric{}, &Index{Score: -0.1}, nil))
	assert.Ok(t, !rule.Test(&Metric{Value: 89}, &Index{Score: 1.3}, nil))
	assert.Ok(t, !rule.Test(&Metric{Value: 189}, &Index{Score: 0.3}, nil))
	// (TrendUp And Value >= X) Or (TrendDown And Value <= X)
	rule = &Rule{TrendUp: true, TrendDown: true, ThresholdMax: 90, ThresholdMin: 10}
	assert.Ok(t, rule.Test(&Metric{Value: 100}, &Index{Score: 1.2}, nil))
	assert.Ok(t, rule.Test(&Metric{Value: 9}, &Index{Score: -1.2}, nil))
	assert.Ok(t, !rule.Test(&Metric{Value: 12}, &Index{Score: 1.2}, nil))
	assert.Ok(t, !rule.Test(&Metric{Value: 102}, &Index{Score: 0.2}, nil))
	assert.Ok(t, !rule.Test(&Metric{Value: 2}, &Index{Score: 0.9}, nil))
	// Default thresholdMaxs
	cfg := config.New()
	cfg.Detector.DefaultThresholdMaxs["fo*"] = 300
	rule = &Rule{TrendUp: true}
	assert.Ok(t, rule.Test(&Metric{Value: 310, Name: "foo"}, &Index{Score: 1.3}, cfg))
	assert.Ok(t, !rule.Test(&Metric{Value: 120, Name: "foo"}, &Index{Score: 1.3}, cfg))
	// Default thresholdMins
	cfg = config.New()
	cfg.Detector.DefaultThresholdMins["fo*"] = 10
	rule = &Rule{TrendDown: true}
	assert.Ok(t, !rule.Test(&Metric{Value: 19, Name: "foo"}, &Index{Score: -1.2}, cfg))
	assert.Ok(t, rule.Test(&Metric{Value: 8, Name: "foo"}, &Index{Score: -1.2}, cfg))
	// Bug#456: DefaultThresholdMax intercepts the testing for later trendDown.
	cfg = config.New()
	cfg.Detector.DefaultThresholdMaxs["fo*"] = 10
	rule = &Rule{TrendDown: true}
	assert.Ok(t, !rule.Test(&Metric{Value: 19, Name: "foo"}, &Index{Score: 0.37}, cfg))
}
Beispiel #2
0
func TestHitLimit(t *testing.T) {
	// Currently disable logging
	log.Disable()
	defer log.Enable()
	//New and add rules.
	config := config.New()
	config.Interval = 1
	rule1 := &models.Rule{Pattern: "a.*.c.d"}
	filter := New()
	filter.addRule(rule1)
	filter.SetHitLimit(config)

	for i := 0; i < config.Detector.IntervalHitLimit; i++ {
		//hit rule when counter < intervalHitLimit
		rules := filter.MatchedRules(&models.Metric{Name: "a.b.c.d"})
		assert.Ok(t, 1 == len(rules))

	}
	//counter over limit, matched rules = 0
	rules := filter.MatchedRules(&models.Metric{Name: "a.b.c.d"})
	assert.Ok(t, 0 == len(rules))
	time.Sleep(time.Second * 2)
	//after interval counter is cleared, matched rules = 1
	rules = filter.MatchedRules(&models.Metric{Name: "a.b.c.d"})
	assert.Ok(t, 1 == len(rules))
}
Beispiel #3
0
func BenchmarkRuleTest(b *testing.B) {
	cfg := config.New()
	m := &Metric{Value: 102}
	idx := &Index{Score: 1.2}
	rule := &Rule{TrendUp: true, ThresholdMax: 100}
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		rule.Test(m, idx, cfg)
	}
}
Beispiel #4
0
func TestAlertRecordAlertNotifyAfterConfigDisabled(t *testing.T) {
	cfg := config.New()
	cfg.Alerter.NotifyAfter = 0
	a := &Alerter{cfg: cfg, alertRecords: safemap.New(), lock: &sync.RWMutex{}}
	metrics := &models.Metric{Name: "test", Stamp: 0, Value: 80}

	for i := 0; i <= 100; i++ {
		metrics.Stamp = uint32(i)
		util.Must(t, !a.checkAlertCount(metrics))
		a.setAlertRecord(metrics)
	}
}
Beispiel #5
0
func TestPickTrendingFactor(t *testing.T) {
	cfg := config.New()
	d := &Detector{cfg: cfg}
	rules := []*models.Rule{
		&models.Rule{Level: models.RuleLevelLow},
	}
	util.Must(t, d.pickTrendingFactor(rules) == cfg.Detector.TrendingFactorLowLevel)
	rules = append(rules, &models.Rule{Level: models.RuleLevelMiddle})
	util.Must(t, d.pickTrendingFactor(rules) == cfg.Detector.TrendingFactorMiddleLevel)
	rules = append(rules, &models.Rule{Level: models.RuleLevelHigh})
	util.Must(t, d.pickTrendingFactor(rules) == cfg.Detector.TrendingFactorHighLevel)
}
Beispiel #6
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()
}
Beispiel #7
0
func TestAlertRecordAlertNotifyAfterConfigSetNotifyAfterToOne(t *testing.T) {
	cfg := config.New()
	cfg.Alerter.NotifyAfter = 1
	a := &Alerter{cfg: cfg, alertRecords: safemap.New(), lock: &sync.RWMutex{}}

	metrics := &models.Metric{Name: "test", Stamp: 80, Value: 80}
	util.Must(t, a.checkAlertCount(metrics))
	a.setAlertRecord(metrics)

	metrics.Stamp = 81
	util.Must(t, !a.checkAlertCount(metrics))
	a.setAlertRecord(metrics)
}
Beispiel #8
0
func BenchmarkRuleTestWithDefaultThresholdMaxsNum4(b *testing.B) {
	cfg := config.New()
	cfg.Detector.DefaultThresholdMaxs = map[string]float64{
		"timer.count_ps.*": 30,
		"timer.upper_90.*": 500,
		"counter.*":        10,
		"timer.mean_90.*":  300,
	}
	m := &Metric{Name: "timer.mean_90.foo", Value: 1700}
	idx := &Index{Name: m.Name, Score: 1.2}
	rule := Rule{TrendUp: true}
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		rule.Test(m, idx, cfg)
	}
}
Beispiel #9
0
func TestFill0Issue470(t *testing.T) {
	// Case https://github.com/eleme/banshee/issues/470
	cfg := config.New()
	d := &Detector{cfg: cfg}
	ms := []*models.Metric{
		&models.Metric{Stamp: 80, Value: 80},
		&models.Metric{Stamp: 90, Value: 90},
		&models.Metric{Stamp: 120, Value: 120},
	}
	start, stop := uint32(60), uint32(150)
	excepted := []float64{80, 90, 0, 0, 120, 0, 0}
	actually := d.fill0(ms, start, stop)
	assert.Ok(t, len(actually) == len(excepted))
	for i := 0; i < len(excepted); i++ {
		assert.Ok(t, excepted[i] == actually[i])
	}
}
Beispiel #10
0
func TestClean(t *testing.T) {
	// Config
	cfg := config.New()
	// Open storage
	dbFileName := "db-test"
	db, _ := storage.Open(dbFileName)
	defer os.RemoveAll(dbFileName)
	defer db.Close()
	// Create cleaner
	c := New(cfg, db)
	// Add outdated data.
	// Case fully cleaned: 3 days no new data
	m1 := &models.Metric{Name: "fully-case", Stamp: uint32(time.Now().Unix() - 3*3600*24 - 1)}
	// Case outdated metrics cleaned.
	m2 := &models.Metric{Name: "metric-case", Stamp: uint32(time.Now().Unix() - 7*3600*24 - 100)}
	m3 := &models.Metric{Name: m2.Name, Stamp: uint32(time.Now().Unix() - 60)}
	i1 := &models.Index{Name: m1.Name, Stamp: m1.Stamp}
	i2 := &models.Index{Name: m2.Name, Stamp: m2.Stamp}
	i3 := &models.Index{Name: m3.Name, Stamp: m3.Stamp}
	// Put metrics.
	db.Metric.Put(m1)
	db.Metric.Put(m2)
	db.Metric.Put(m3)
	// Put indexes.
	db.Index.Put(i1)
	db.Index.Put(i2)
	db.Index.Put(i3)
	c.clean()
	// m1 should be fully cleaned
	var err error
	_, err = db.Index.Get(m1.Name)
	assert.Ok(t, err == indexdb.ErrNotFound)
	l, err := db.Metric.Get(m1.Name, 0, uint32(time.Now().Unix()))
	assert.Ok(t, len(l) == 0)
	// m2 should be cleaned and m3 shouldn't be cleaned
	l, err = db.Metric.Get(m2.Name, m2.Stamp, uint32(time.Now().Unix()))
	assert.Ok(t, len(l) == 1)
	assert.Ok(t, l[0].Name == m2.Name)
	assert.Ok(t, l[0].Stamp == m3.Stamp && l[0].Stamp != m2.Stamp)
	// m2/m3's index shouldn't be cleaned
	i, err := db.Index.Get(m2.Name)
	assert.Ok(t, err == nil && i.Name == m2.Name)
}
Beispiel #11
0
	"github.com/eleme/banshee/detector"
	"github.com/eleme/banshee/filter"
	"github.com/eleme/banshee/health"
	"github.com/eleme/banshee/storage"
	"github.com/eleme/banshee/util/log"
	"github.com/eleme/banshee/version"
	"github.com/eleme/banshee/webapp"
)

var (
	// Arguments
	debug       = flag.Bool("d", false, "debug mode")
	fileName    = flag.String("c", "config.json", "config file path")
	showVersion = flag.Bool("v", false, "show version")
	// Variables
	cfg = config.New()
	db  *storage.DB
	flt = filter.New()
)

func usage() {
	fmt.Fprintf(os.Stderr, "usage: banshee [-c config] [-d] [-v]\n")
	flag.PrintDefaults()
	fmt.Fprintf(os.Stderr, "copyright eleme https://github.com/eleme/banshee.\n")
	os.Exit(2)
}

func initLog() {
	log.SetName("banshee")
	if *debug {
		log.SetLevel(log.DEBUG)