Beispiel #1
0
//Sets any invalid fields to their default value
func PerformDefault(conf Configuration) {
	err := conf.Validate()
	name := reflect.ValueOf(conf).Type()
	if err != nil {
		if errs, ok := err.(validator.ErrorMap); ok {
			for fieldName := range errs {
				if strings.Contains(fieldName, ".") {
					//If field Name contains a '.' than it is a subfield of a current field
					continue
				}
				glog.V(4).Info("Invalid field searching for default ", fieldName)
				if ok, err := defaults.HasDefault(conf, fieldName); ok {
					value, err := defaults.SetDefault(conf, fieldName)
					if err != nil {
						glog.Errorf("Failed to set default of %s on %s", fieldName, name)
					} else {
						glog.Infof("Defaulted %v.%s to '%v'", name, fieldName, value)
					}
				} else {
					glog.V(4).Info("No default found: ", err)
				}
			}
		} else {
			glog.Errorf("Failed to validate %s: %s", name, err)
		}
	}
}
Beispiel #2
0
func (self *ScheduledQuery) callback(start, stop time.Time) {
	query := self.builder.GetForTimeRange(start, stop)
	if self.callback != nil {
		glog.V(1).Info("Scheduling query:", query)
		self.Callback(query)
	}
}
Beispiel #3
0
// Determine if the window is anomalous
func (self *Detector) IsAnomalous(window *Window) bool {

	self.Stats.WindowCount++
	self.Stats.DataPointCount += uint64(len(window.Data))

	vote := 0.0
	for _, fc := range self.counters {
		fingerprint := fc.fingerprinter.Fingerprint(window.Copy())
		count := fc.counter.Count(fingerprint)
		if count < self.normalCount {
			vote++
		}
	}

	vote /= float64(len(self.counters))
	anomalous := vote >= self.consensus

	glog.V(3).Infof("Window anomalous: %v vote: %f, consensus: %f", anomalous, vote, self.consensus)

	if anomalous {
		self.Stats.AnomalousCount++
	}

	return anomalous
}
Beispiel #4
0
func (self *Schedule) Start() error {
	if self.running {
		return errors.New("Schedule already started")
	}
	self.running = true

	stop := time.Now()
	if self.Period > day {
		stop = stop.Truncate(day)
	} else {
		stop = stop.Truncate(self.Period)
	}
	stop = stop.Add(self.Period)
	go func(stop time.Time, period time.Duration) {
		now := time.Now()
		glog.V(2).Info("Starting schedule", stop.Add(self.Delay), stop.Add(self.Delay).Sub(now))
		time.Sleep(stop.Add(self.Delay).Sub(now))
		ticker := time.NewTicker(period)
		for self.running {
			self.Callback(stop.Add(-period), stop)
			stop = stop.Add(period)
			<-ticker.C
		}
		ticker.Stop()
	}(stop, self.Period)
	return nil
}
Beispiel #5
0
// Register a Factory by name
func (self *Registery) RegisterFactory(name string, factory Factory) error {
	glog.V(2).Infof("Registering Factory %s", name)
	if _, ok := self.factories[name]; ok {
		return errors.New(fmt.Sprintf("Factory of name %s already registered"))
	}
	self.factories[name] = factory
	return nil
}
Beispiel #6
0
func (self *Sigma) Fingerprint(window morgoth.Window) morgoth.Fingerprint {

	mean, std := calcStats(window.Data)
	glog.V(4).Infof("N: %d Mean: %f Std: %f", len(window.Data), mean, std)
	return SigmaFingerprint{
		mean:      mean,
		threshold: self.deviations * std,
	}
}
Beispiel #7
0
func (self *Manager) processQueries() {
	for query := range self.queryQueue {
		glog.V(2).Info("Executing query:", query)
		windows, err := self.engine.GetWindows(query.query)
		if err != nil {
			glog.Errorf("Failed to execute query: '%s' %s", query, err)
			continue
		}
		// Tag windows with query tags
		glog.V(3).Info("Adding query tags: ", query.tags)
		for _, w := range windows {
			for t, v := range query.tags {
				w.Tags[t] = v
			}
		}

		self.ProcessWindows(windows)
	}
}
Beispiel #8
0
func (self *AlertsManager) processQueries() {
	for query := range self.queryQueue {
		glog.V(2).Info("Executing query:", query)
		windows, err := self.engine.GetWindows(query.query)
		if err != nil {
			glog.Errorf("Failed to execute query: '%s' %s", query, err)
			continue
		}
		glog.Info(windows)

		for _, w := range windows {
			sum := 0.0
			for _, point := range w.Data {
				sum += point
			}
			glog.V(1).Info("Alert Query total ", sum)
			if sum > query.threshold {
				for _, n := range query.notifiers {
					n.Notify(query.message, w)
				}
			}
		}
	}
}
Beispiel #9
0
func (self Config) Validate() (err error) {
	glog.V(2).Info("Validating Config")
	err = validator.Validate(self)
	if err != nil {
		return
	}
	err = self.EngineConf.Validate()
	if err != nil {
		return
	}
	for _, mp := range self.Mappings {
		err = mp.Validate()
		if err != nil {
			return
		}
	}
	return
}
Beispiel #10
0
func (self *APIServer) Start() (err error) {
	self.handler = rest.ResourceHandler{
		EnableStatusService: true,
	}
	self.handler.SetRoutes(
		&rest.Route{"GET", "/status", self.status},
		&rest.Route{"GET", "/stats", self.stats},
	)
	self.listener, err = net.Listen("tcp", fmt.Sprintf(":%d", self.port))
	if err != nil {
		glog.Errorf("Error binding APIServer: %s", err)
		return
	}
	go func() {
		err = http.Serve(self.listener, &self.handler)
		if err != nil {
			glog.Errorf("Error while APIServer was running: %s", err)
		}
	}()
	glog.V(1).Info("APIServer running")
	return
}
Beispiel #11
0
func (self *Manager) Start() (err error) {
	for _, sq := range self.scheduledDataQueries {
		sq.Start(self.queryQueue)
	}

	self.db, err = bolt.Open("morgoth.db", 0600, nil)
	if err != nil {
		return
	}

	self.db.Update(func(tx *bolt.Tx) error {
		_, err := tx.CreateBucketIfNotExists([]byte("morgoth"))
		if err != nil {
			return err
		}
		return nil
	})
	self.db.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte("morgoth"))
		mappingBytes := bytes.NewBuffer(b.Get([]byte("mappings")))
		dec := gob.NewDecoder(mappingBytes)
		mappings := make([]*DetectorMapper, 0)
		err := dec.Decode(&mappings)
		if err != nil {
			return err
		}
		for _, m := range mappings {
			self.mapper.addDetectorMapper(m)
		}
		return nil
	})

	glog.V(1).Infof("Starting %d processQueries routines", workerCount)
	for i := 0; i < workerCount; i++ {
		go self.processQueries()
	}
	return
}
Beispiel #12
0
func (self *App) Run() (err error) {
	glog.Info("Starting app")
	glog.Info("Setup signal handler")
	go self.signalHandler()

	glog.Info("Setup Engine")
	self.engine, err = self.config.EngineConf.GetEngine()
	if err != nil {
		return
	}
	err = self.engine.Initialize()
	if err != nil {
		return
	}

	glog.Info("Setup Mapper")
	detectorMatchers := make([]*DetectorMatcher, len(self.config.Mappings))
	for i, mapping := range self.config.Mappings {
		namePattern, err := regexp.Compile(mapping.Name)
		if err != nil {
			return fmt.Errorf("Error parsing regexp: %s: %s", mapping.Name, err)
		}
		tagPatterns := make(map[string]*regexp.Regexp, len(mapping.Tags))
		for tag, pattern := range mapping.Tags {
			r, err := regexp.Compile(pattern)
			if err != nil {
				return fmt.Errorf("Error parsing regexp: %s: %s", pattern, err)
			}
			tagPatterns[tag] = r
		}
		fingerprinters := make([]Fingerprinter, len(mapping.Detector.Fingerprinters))
		for i, fp := range mapping.Detector.Fingerprinters {
			f, err := fp.GetFingerprinter()
			if err != nil {
				return fmt.Errorf("Error creating Fingerprinter: %s", err)
			}

			fingerprinters[i] = f
		}
		detectorBuilder := NewDetectorBuilder(
			mapping.Detector.NormalCount,
			mapping.Detector.Consensus,
			mapping.Detector.MinSupport,
			mapping.Detector.ErrorTolerance,
			fingerprinters,
		)
		glog.V(1).Infof("Created detector builder: %v", mapping.Detector)
		matcher := NewDetectorMatcher(namePattern, tagPatterns, detectorBuilder)
		glog.V(1).Infof("Created detector matcher: %v", matcher)
		detectorMatchers[i] = matcher

	}
	detectorMappers := make([]*DetectorMapper, 0)
	self.mapper = NewMapper(detectorMappers, detectorMatchers)
	self.Stats.MapperStats = &self.mapper.Stats

	glog.Info("Setup Manager")
	scheduledDataQueries := make([]*scheduledDataQuery, len(self.config.Schedules))
	for i, sc := range self.config.Schedules {
		builder, err := self.engine.NewQueryBuilder(sc.Query, sc.GroupByInterval)
		if err != nil {
			return fmt.Errorf("Invalid query string: '%s', %s", sc.Query, err)
		}
		q := &scheduledDataQuery{
			sq: NewScheduledQuery(
				builder,
				sc.Delay,
				sc.Period,
			),
			tags: sc.Tags,
		}
		scheduledDataQueries[i] = q
	}

	self.manager = NewManager(self.mapper, self.engine, scheduledDataQueries)

	glog.Info("Starting Manager...")
	self.manager.Start()

	glog.Infof("Starting APIServer on :%d", self.config.APIPort)
	self.apiServer = NewAPIServer(self, self.config.APIPort)
	self.apiServer.Start()

	glog.Infof("Starting Alert Manger...")
	scheduledAlertQueries := make([]*scheduledAlertQuery, len(self.config.Alerts))
	for i, ac := range self.config.Alerts {
		builder, err := self.engine.NewQueryBuilder(ac.Query, ac.GroupByInterval)
		if err != nil {
			return fmt.Errorf("Invalid query string: '%s', %s", ac.Query, err)
		}

		notifiers := make([]Notifier, len(ac.Notifiers))
		for i, nc := range ac.Notifiers {
			n, err := nc.GetNotifier()
			if err != nil {
				return fmt.Errorf("Invalid Notifier for query: '%s' Err: %s", ac.Query, err)
			}
			notifiers[i] = n
		}

		q := &scheduledAlertQuery{
			sq: NewScheduledQuery(
				builder,
				ac.Delay,
				ac.Period,
			),
			threshold: ac.Threshold,
			notifiers: notifiers,
			message:   ac.Message,
		}

		scheduledAlertQueries[i] = q
	}

	self.alertsManager = NewAlertsManager(self.engine, scheduledAlertQueries)
	self.alertsManager.Start()

	// Wait for shutdown
	<-self.shutdownChan

	// Begin shutdown
	self.manager.Stop()
	self.apiServer.Stop()

	glog.Info("App shutdown")
	return
}
Beispiel #13
0
func (self *InfluxDBEngine) GetWindows(query morgoth.Query) ([]*morgoth.Window, error) {

	con, err := client.NewClient(self.conf)
	if err != nil {
		return nil, err
	}

	q := client.Query{
		Command:  query.Command,
		Database: self.database,
	}

	glog.V(3).Infof("Q: %s", query)
	response, err := con.Query(q)
	if err != nil {
		return nil, err
	}
	if response.Err != nil {
		return nil, response.Err
	}
	windowCount := 0
	for _, result := range response.Results {
		if result.Err != nil {
			return nil, result.Err
		}
		windowCount += len(result.Series)
	}
	windows := make([]*morgoth.Window, windowCount)

	glog.V(3).Infof("Results: %v", response.Results)

	i := 0
	for _, result := range response.Results {
		for _, row := range result.Series {
			w := &morgoth.Window{
				Name:  row.Name,
				Data:  make([]float64, len(row.Values)),
				Tags:  row.Tags,
				Start: query.Start,
				Stop:  query.Stop,
			}

			//Find non time column
			if len(row.Columns) != 2 {
				return nil, errors.New("Queries must select only two columns, a time column and a numeric column")
			}
			numberColumn := 0
			for c, name := range row.Columns {
				if name != "time" {
					numberColumn = c
					break
				}
			}

			for j, point := range row.Values {
				//We care only about the value not the time
				//TODO check columns
				value := point[numberColumn]
				if value != nil {
					p := value.(json.Number)
					v, err := p.Float64()
					if err != nil {
						return nil, err
					}
					w.Data[j] = v
				}
			}

			windows[i] = w
			i++
			glog.V(4).Infof("W: %v", w)
		}
	}

	glog.V(3).Infof("Windows: %v", windows)
	return windows, nil
}