Example #1
0
// Get history values for the input metric, will only fetch the history
// values with the same phase around this timestamp, within an filter
// offset.
func (d *Detector) values(m *models.Metric, fz bool) ([]float64, error) {
	timer := util.NewTimer()
	defer func() {
		elapsed := timer.Elapsed()
		health.AddQueryCost(elapsed)
	}()
	offset := uint32(d.cfg.Detector.FilterOffset * float64(d.cfg.Period))
	expiration := d.cfg.Expiration
	period := d.cfg.Period
	ftimes := d.cfg.Detector.FilterTimes
	// Get values with the same phase.
	n := 0 // number of goroutines to luanch
	ch := make(chan metricGetResult)
	var stamp uint32
	if d.cfg.Detector.UsingRecentDataPoints {
		stamp = m.Stamp
	} else {
		stamp = m.Stamp - period
	}
	for ; stamp+expiration > m.Stamp; stamp -= period {
		start := stamp - offset
		stop := stamp + offset
		// Range (m.Stamp,m.Stamp+offset) has no data as it is the future
		if stamp == m.Stamp {
			stop = m.Stamp
		}
		go func() {
			ms, err := d.db.Metric.Get(m.Name, m.Link, start, stop)
			ch <- metricGetResult{err, ms, start, stop}
		}()
		n++
		if n >= ftimes {
			break
		}
	}
	// Concat chunks.
	var vals []float64
	var err error
	for i := 0; i < n; i++ {
		r := <-ch
		if r.err != nil {
			// Record error but DONOT return directly.
			// Must receive n times from ch, otherwise the goroutine will
			// be hanged and the ch won't be gc, yet memory leaks.
			err = r.err
			continue
		}
		if err != nil {
			continue
		}
		// Append to values.
		if !fz {
			for j := 0; j < len(r.ms); j++ {
				vals = append(vals, r.ms[j].Value)
			}
		} else {
			// Fill blank with zeros.
			vals = append(vals, d.fill0(r.ms, r.start, r.stop)...)
		}
	}
	return vals, err
}
Example #2
0
// Get history values for the input metric, will only fetch the history
// values with the same phase around this timestamp, within an filter
// offset.
func (d *Detector) values(m *models.Metric, fz bool) ([]float64, error) {
	timer := util.NewTimer()
	defer func() {
		elapsed := timer.Elapsed()
		health.AddQueryCost(elapsed)
	}()
	offset := uint32(d.cfg.Detector.FilterOffset * float64(d.cfg.Period))
	expiration := d.cfg.Expiration
	period := d.cfg.Period
	ftimes := d.cfg.Detector.FilterTimes
	k := int(math.Ceil(float64(expiration) / float64(period)))
	s := rand.Perm(k)[:ftimes]
	mp := make(map[int]bool, ftimes)
	for _, v := range s {
		mp[v] = true
	}
	// Get values with the same phase.
	n := 0 // number of goroutines to luanch
	i := 0 // index of the following loop
	ch := make(chan metricGetResult)
	for stamp := m.Stamp; stamp+expiration > m.Stamp; stamp -= period {
		start := stamp - offset
		stop := stamp + offset
		if mp[i] {
			go func() {
				ms, err := d.db.Metric.Get(m.Name, start, stop)
				ch <- metricGetResult{err, ms, start, stop}
			}()
			n++
		}
		i++
	}
	// Concat chunks.
	var vals []float64
	var err error
	for i := 0; i < n; i++ {
		r := <-ch
		if r.err != nil {
			// Record error but DONOT return directly.
			// Must receive n times from ch, otherwise the goroutine will
			// be hanged and the ch won't be gc, yet memory leaks.
			err = r.err
			continue
		}
		if err != nil {
			continue
		}
		// Append to values.
		if !fz {
			for j := 0; j < len(r.ms); j++ {
				vals = append(vals, r.ms[j].Value)
			}
		} else {
			// Fill blank with zeros.
			vals = append(vals, d.fill0(r.ms, r.start, r.stop)...)
		}
	}
	if err != nil {
		// Unexcepted error
		return vals, err
	}
	// Append m
	vals = append(vals, m.Value)
	return vals, nil
}