Exemple #1
0
// parseTcollectorValue parses a tcollector-style line into a data point.
func parseTcollectorValue(line string) (*opentsdb.DataPoint, error) {
	sp := strings.Fields(line)
	if len(sp) < 3 {
		return nil, fmt.Errorf("bad line: %s", line)
	}
	ts, err := strconv.ParseInt(sp[1], 10, 64)
	if err != nil {
		return nil, fmt.Errorf("bad timestamp: %s", sp[1])
	}
	val, err := strconv.ParseFloat(sp[2], 64)
	if err != nil {
		return nil, fmt.Errorf("bad value: %s", sp[2])
	}
	if !opentsdb.ValidTag(sp[0]) {
		return nil, fmt.Errorf("bad metric: %s", sp[0])
	}
	dp := opentsdb.DataPoint{
		Metric:    sp[0],
		Timestamp: ts,
		Value:     val,
	}
	tags := opentsdb.TagSet{}
	for _, tag := range sp[3:] {
		ts, err := opentsdb.ParseTags(tag)
		if err != nil {
			return nil, fmt.Errorf("bad tag, metric %s: %v: %v", sp[0], tag, err)
		}
		tags.Merge(ts)
	}
	setExternalTags(tags)
	dp.Tags = tags
	return &dp, nil
}
func BenchmarkSimpleRewrite(b *testing.B) {
	rule := &DenormalizationRule{
		Metric:   "a.b.c",
		TagNames: []string{"host"},
	}
	tags := opentsdb.TagSet{"host": "foo-bar", "baz": "qwerty"}
	dp := &opentsdb.DataPoint{
		Metric:    "a.b.c",
		Timestamp: 42,
		Value:     3,
		Tags:      tags.Copy(),
	}
	for i := 0; i < b.N; i++ {
		err := rule.Translate(dp)
		if err != nil {
			b.Fatal(err)
		}
		//expectedName := "__foo-bar.a.b.c"
		/*	if dp.Metric != expectedName {
					b.Errorf("metric name %s is not `%s`", dp.Metric, expectedName)
				}
				if dp.Timestamp != 42 {
					b.Errorf("new metric timestamp does not match. %d != 42", dp.Timestamp)
				}
				if dp.Value != 3 {
					b.Errorf("new metric value does not match. %d != 3", dp.Value)
				}
				if !dp.Tags.Equal(tags) {
					b.Errorf("new metric tags do not match. %v != %v", dp.Tags, tags)
		        } */
	}
}
Exemple #3
0
func (to *TagOverride) AddTags(t opentsdb.TagSet) {
	if to.tags == nil {
		to.tags = t.Copy()
	} else {
		to.tags = to.tags.Merge(t)
	}
}
Exemple #4
0
// AddMeta adds a metadata entry to memory, which is queued for later sending.
func AddMeta(metric string, tags opentsdb.TagSet, name string, value interface{}, setHost bool) {
	if tags == nil {
		tags = make(opentsdb.TagSet)
	}
	if _, present := tags["host"]; setHost && !present {
		tags["host"] = util.Hostname
	}
	if err := tags.Clean(); err != nil {
		slog.Error(err)
		return
	}
	ts := tags.Tags()
	metalock.Lock()
	defer metalock.Unlock()
	prev, present := metadata[Metakey{metric, ts, name}]
	if present && !reflect.DeepEqual(prev, value) {
		slog.Infof("metadata changed for %s/%s/%s: %v to %v", metric, ts, name, prev, value)
		go sendMetadata([]Metasend{{
			Metric: metric,
			Tags:   tags,
			Name:   name,
			Value:  value,
		}})
	} else if metadebug {
		slog.Infof("AddMeta for %s/%s/%s: %v", metric, ts, name, value)
	}
	metadata[Metakey{metric, ts, name}] = value
}
Exemple #5
0
// AddTS is the same as Add but lets you specify the timestamp
func AddTS(md *opentsdb.MultiDataPoint, name string, ts int64, value interface{}, t opentsdb.TagSet, rate metadata.RateType, unit metadata.Unit, desc string) {
	if b, ok := value.(bool); ok {
		if b {
			value = 1
		} else {
			value = 0
		}
	}
	tags := t.Copy()
	if host, present := tags["host"]; !present {
		tags["host"] = util.Hostname
	} else if host == "" {
		delete(tags, "host")
	}
	if rate != metadata.Unknown {
		metadata.AddMeta(name, nil, "rate", rate, false)
	}
	if unit != metadata.None {
		metadata.AddMeta(name, nil, "unit", unit, false)
	}
	if desc != "" {
		metadata.AddMeta(name, tags, "desc", desc, false)
	}

	tags = AddTags.Copy().Merge(tags)
	d := opentsdb.DataPoint{
		Metric:    name,
		Timestamp: ts,
		Value:     value,
		Tags:      tags,
	}
	*md = append(*md, &d)
}
Exemple #6
0
// Put is useful for capturing "events" that have a gauge value. Subsequent
// calls between the sending interval will overwrite previous calls.
func Put(metric string, ts opentsdb.TagSet, v interface{}) error {
	if err := check(metric, &ts); err != nil {
		return err
	}
	tss := metric + ts.String()
	mlock.Lock()
	puts[tss] = &putMetric{metric, ts.Copy(), v}
	mlock.Unlock()
	return nil
}
Exemple #7
0
// Set registers a callback for the given metric and tags, calling f immediately
// before queueing data for send.
func Set(metric string, ts opentsdb.TagSet, f func() interface{}) error {
	if err := check(metric, &ts); err != nil {
		return err
	}
	tss := metric + ts.String()
	mlock.Lock()
	sets[tss] = &setMetric{metric, ts.Copy(), f}
	mlock.Unlock()
	return nil
}
Exemple #8
0
// AddTS is the same as Add but lets you specify the timestamp
func AddTS(md *opentsdb.MultiDataPoint, name string, ts int64, value interface{}, t opentsdb.TagSet, rate metadata.RateType, unit metadata.Unit, desc string) {
	// Check if we really want that metric
	if skipMetric(name) {
		return
	}

	tags := t.Copy()
	if host, present := tags["host"]; !present {
		tags["host"] = util.Hostname
	} else if host == "" {
		delete(tags, "host")
	}
	// if tags are not cleanable, log a message and skip it
	if err := tags.Clean(); err != nil {
		line := ""
		//attempt to log where Add was called from
		if _, filename, l, ok := runtime.Caller(1); ok {
			if filepath.Base(filename) == "collectors.go" {
				_, filename, l, ok = runtime.Caller(2)
			}
			if ok {
				line = fmt.Sprintf("%s:%d", filepath.Base(filename), l)
			}
		}
		slog.Errorf("Invalid tagset discovered: %s. Skipping datapoint. Added from: %s", tags.String(), line)
		return
	}
	if rate != metadata.Unknown {
		metadata.AddMeta(name, nil, "rate", rate, false)
	}
	if unit != metadata.None {
		metadata.AddMeta(name, nil, "unit", unit, false)
	}
	if desc != "" {
		metadata.AddMeta(name, tags, "desc", desc, false)
	}
	tags = AddTags.Copy().Merge(tags)
	if b, ok := value.(bool); ok {
		if b {
			value = 1
		} else {
			value = 0
		}
	}
	d := opentsdb.DataPoint{
		Metric:    name,
		Timestamp: ts,
		Value:     value,
		Tags:      tags,
	}
	*md = append(*md, &d)
}
Exemple #9
0
// GetLast returns the value of the most recent data point for the given metric
// and tag. tags should be of the form "{key=val,key2=val2}". If diff is true,
// the value is treated as a counter. err is non nil if there is no match.
func (s *Search) GetLast(metric string, tags opentsdb.TagSet, diff bool) (v float64, err error) {
	s.RLock()
	defer s.RUnlock()

	if mmap := s.last[metric]; mmap != nil {
		if p := mmap[tags.String()]; p != nil {
			if diff {
				return p.DiffFromPrev, nil
			}
			return p.LastVal, nil
		}
	}
	return 0, nil
}
Exemple #10
0
func Sample(metric string, ts opentsdb.TagSet, v float64) error {
	if err := check(metric, &ts); err != nil {
		return err
	}
	tss := metric + ts.String()
	mlock.Lock()
	if aggs[tss] == nil {
		aggs[tss] = &agMetric{
			metric: metric,
			ts:     ts.Copy(),
		}
	}
	aggs[tss].values = append(aggs[tss].values, v)
	mlock.Unlock()
	return nil
}
Exemple #11
0
// Add takes a metric and increments a counter for that metric. The metric name
// is appended to the basename specified in the Init function.
func Add(metric string, ts opentsdb.TagSet, inc int64) error {
	if err := check(metric, &ts); err != nil {
		return err
	}
	tss := metric + ts.String()
	mlock.Lock()
	if counters[tss] == nil {
		counters[tss] = &addMetric{
			metric: metric,
			ts:     ts.Copy(),
		}
	}
	counters[tss].value += inc
	mlock.Unlock()
	return nil
}
Exemple #12
0
func c_fortinet_os(host, community string, cpuIntegrators map[string]tsIntegrator) (opentsdb.MultiDataPoint, error) {
	var md opentsdb.MultiDataPoint
	ts := opentsdb.TagSet{"host": host}
	// CPU
	cpuRaw, err := snmp_subtree(host, community, fortinetBaseOID+fortinetCPU)
	if err != nil {
		return md, err
	}
	coreCount := len(cpuRaw)
	var totalPercent int
	for id, v := range cpuRaw {
		cpuVal, err := strconv.Atoi(fmt.Sprintf("%v", v))
		if err != nil {
			return md, fmt.Errorf("couldn't convert cpu value to int for fortinet cpu utilization on host %v: %v", host, err)
		}
		ts := ts.Copy().Merge(opentsdb.TagSet{"processor": id})
		Add(&md, "fortinet.cpu.percent_used", cpuVal, ts, metadata.Gauge, metadata.Pct, "")
		totalPercent += cpuVal
	}
	if _, ok := cpuIntegrators[host]; !ok {
		cpuIntegrators[host] = getTsIntegrator()
	}
	Add(&md, osCPU, cpuIntegrators[host](time.Now().Unix(), float64(totalPercent)/float64(coreCount)), opentsdb.TagSet{"host": host}, metadata.Counter, metadata.Pct, "")

	// Memory
	memTotal, err := snmp_oid(host, community, fortinetBaseOID+fortinetMemTotal)
	if err != nil {
		return md, fmt.Errorf("failed to get total memory for fortinet host %v: %v", host, err)
	}
	memTotalBytes := memTotal.Int64() * 2 << 9 // KiB to Bytes
	Add(&md, "fortinet.mem.total", memTotal, ts, metadata.Gauge, metadata.KBytes, "The total memory in kilobytes.")
	Add(&md, osMemTotal, memTotalBytes, ts, metadata.Gauge, metadata.Bytes, osMemTotalDesc)
	memPctUsed, err := snmp_oid(host, community, fortinetBaseOID+fortinetMemPercentUsed)
	if err != nil {
		return md, fmt.Errorf("failed to get percent of memory used for fortinet host %v: %v", host, err)
	}
	Add(&md, "fortinet.mem.percent_used", memPctUsed, ts, metadata.Gauge, metadata.Pct, "The percent of memory used.")
	memPctUsedFloat := float64(memPctUsed.Int64()) / 100
	memPctFree := 100 - memPctUsed.Int64()
	Add(&md, osMemPctFree, memPctFree, ts, metadata.Gauge, metadata.Pct, osMemPctFreeDesc)
	memFree := float64(memTotalBytes) * (float64(1) - memPctUsedFloat)
	Add(&md, osMemFree, int64(memFree), ts, metadata.Gauge, metadata.Bytes, osMemFreeDesc)
	Add(&md, osMemUsed, int64(float64(memTotalBytes)-memFree), ts, metadata.Gauge, metadata.Bytes, osMemUsedDesc)

	return md, nil
}
Exemple #13
0
func (to *TagOverride) AddTagOverrides(sources map[string]string, t opentsdb.TagSet) error {
	if to.matchedTags == nil {
		to.matchedTags = make(map[string]*regexp.Regexp)
	}
	var err error
	for tag, re := range sources {
		to.matchedTags[tag], err = regexp.Compile(re)
		if err != nil {
			return fmt.Errorf("invalid regexp: %s error: %s", re, err)
		}
	}

	if to.tags == nil {
		to.tags = t.Copy()
	} else {
		to.tags = to.tags.Merge(t)
	}

	return nil
}
Exemple #14
0
func TestTagMetadata_RoundTrip(t *testing.T) {
	host := randString(4)
	tagset := opentsdb.TagSet{"host": host, "iface": "foo", "iname": "bar", "direction": "in"}
	if err := testData.Metadata().PutTagMetadata(tagset, "alias", "foo", time.Now()); err != nil {
		t.Fatal(err)
	}
	metas, err := testData.Metadata().GetTagMetadata(tagset, "alias")
	if err != nil {
		t.Fatal(err)
	}
	if len(metas) != 1 {
		t.Fatal("expected 1 metadata result")
	}
	m := metas[0]
	if m.Name != "alias" {
		t.Fatalf("name %s != alias", m.Name)
	}
	if !m.Tags.Equal(tagset) {
		t.Fatalf("tagset %s != %s", m.Tags.String(), tagset.String())
	}
}
Exemple #15
0
func rabbitmqBackingQueueStatus(p string, ts opentsdb.TagSet, bqs rmqBackingQueueStatus) opentsdb.MultiDataPoint {
	var md opentsdb.MultiDataPoint
	Add(&md, p+"avg_rate", bqs.AvgAckEgressRate, ts.Copy().Merge(opentsdb.TagSet{"method": "ack", "direction": "out"}),
		metadata.Rate, metadata.Message, DescRmqBackingQueueStatusAvgAckEgressRate)
	Add(&md, p+"avg_rate", bqs.AvgAckIngressRate, ts.Copy().Merge(opentsdb.TagSet{"method": "ack", "direction": "in"}),
		metadata.Rate, metadata.Message, DescRmqBackingQueueStatusAvgAckIngressRate)
	Add(&md, p+"avg_rate", bqs.AvgEgressRate, ts.Copy().Merge(opentsdb.TagSet{"method": "noack", "direction": "out"}),
		metadata.Rate, metadata.Message, DescRmqBackingQueueStatusAvgEgressRate)
	Add(&md, p+"avg_rate", bqs.AvgIngressRate, ts.Copy().Merge(opentsdb.TagSet{"method": "noack", "direction": "in"}),
		metadata.Rate, metadata.Message, DescRmqBackingQueueStatusAvgIngressRate)
	Add(&md, p+"len", bqs.Len, ts,
		metadata.Gauge, metadata.Message, DescRmqBackingQueueStatusLen)
	return md
}
Exemple #16
0
func haproxyFetch(user, pwd, tier, url string) (opentsdb.MultiDataPoint, error) {
	var md opentsdb.MultiDataPoint
	var err error
	const metric = "haproxy"
	parse := func(v string) (int64, error) {
		var i int64
		if v != "" {
			i, err = strconv.ParseInt(v, 10, 64)
			if err != nil {
				return 0, err
			}
			return i, nil
		}
		return i, nil
	}

	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}
	// Close connection after request. Default cached connections will get
	// failures in the event of server closing idle connections.
	// See https://github.com/golang/go/issues/8946
	req.Close = true
	req.SetBasicAuth(user, pwd)
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	reader := csv.NewReader(resp.Body)
	records, err := reader.ReadAll()
	if err != nil {
		return nil, err
	}
	if len(records) < 2 {
		return nil, nil
	}
	for _, rec := range records[1:] {
		// There is a trailing comma in haproxy's csv
		if len(rec) != len(haproxyCSVMeta)+1 {
			return nil, fmt.Errorf("expected %v lines. got: %v",
				len(haproxyCSVMeta)+1, len(rec))
		}
		hType := haproxyType[rec[32]]
		pxname := rec[0]
		svname := rec[1]
		ts := opentsdb.TagSet{"pxname": pxname, "svname": svname, "tier": tier}
		for i, field := range haproxyCSVMeta {
			m := strings.Join([]string{metric, hType, field.Name}, ".")
			value := rec[i]
			if field.Ignore == true {
				continue
			} else if strings.HasPrefix(field.Name, "hrsp") {
				sp := strings.Split(field.Name, "_")
				if len(sp) != 2 {
					return nil, fmt.Errorf("unexpected field name %v in hrsp", field.Name)
				}
				ts := ts.Copy().Merge(opentsdb.TagSet{"status_code": sp[1]})
				m = strings.Join([]string{metric, hType, sp[0]}, ".")
				v, err := parse(value)
				if err != nil {
					return nil, err
				}
				Add(&md, m, v, ts, metadata.Counter, metadata.Response,
					fmt.Sprintf("The number of http responses with a %v status code.", sp[1]))
			} else if field.Name == "status" {
				v, ok := haproxyStatus[value]
				// Not distinging between MAINT and MAINT via...
				if !ok {
					v = 3
				}
				Add(&md, m, v, ts, field.RateType, field.Unit, field.Desc)
			} else if field.Name == "check_status" {
				if value == "" {
					continue
				}
				v, ok := haproxyCheckStatus[value]
				if !ok {
					return nil, fmt.Errorf("unknown check status %v", value)
				}
				Add(&md, m, v, ts, field.RateType, field.Unit, field.Desc)
			} else {
				v, err := parse(value)
				if err != nil {
					return nil, err
				}
				Add(&md, m, v, ts, field.RateType, field.Unit, field.Desc)
			}
		}
	}
	return md, nil
}
Exemple #17
0
// CollectStates sends various state information to bosun with collect.
func (s *Schedule) CollectStates() {
	// [AlertName][Severity]Count
	severityCounts := make(map[string]map[string]int64)
	abnormalCounts := make(map[string]map[string]int64)
	ackStatusCounts := make(map[string]map[bool]int64)
	ackByNotificationCounts := make(map[string]map[bool]int64)
	unAckOldestByNotification := make(map[string]time.Time)
	activeStatusCounts := make(map[string]map[bool]int64)
	// Initalize the Counts
	for _, alert := range s.Conf.Alerts {
		severityCounts[alert.Name] = make(map[string]int64)
		abnormalCounts[alert.Name] = make(map[string]int64)
		var i models.Status
		for i = 1; i.String() != "none"; i++ {
			severityCounts[alert.Name][i.String()] = 0
			abnormalCounts[alert.Name][i.String()] = 0
		}
		ackStatusCounts[alert.Name] = make(map[bool]int64)
		activeStatusCounts[alert.Name] = make(map[bool]int64)
		ackStatusCounts[alert.Name][false] = 0
		activeStatusCounts[alert.Name][false] = 0
		ackStatusCounts[alert.Name][true] = 0
		activeStatusCounts[alert.Name][true] = 0
	}
	for notificationName := range s.Conf.Notifications {
		unAckOldestByNotification[notificationName] = time.Unix(1<<63-62135596801, 999999999)
		ackByNotificationCounts[notificationName] = make(map[bool]int64)
		ackByNotificationCounts[notificationName][false] = 0
		ackByNotificationCounts[notificationName][true] = 0
	}
	//TODO:
	//	for _, state := range s.status {
	//		if !state.Open {
	//			continue
	//		}
	//		name := state.AlertKey.Name()
	//		alertDef := s.Conf.Alerts[name]
	//		nots := make(map[string]bool)
	//		for name := range alertDef.WarnNotification.Get(s.Conf, state.Group) {
	//			nots[name] = true
	//		}
	//		for name := range alertDef.CritNotification.Get(s.Conf, state.Group) {
	//			nots[name] = true
	//		}
	//		incident, err := s.GetIncident(state.Last().IncidentId)
	//		if err != nil {
	//			slog.Errorln(err)
	//		}
	//		for notificationName := range nots {
	//			ackByNotificationCounts[notificationName][state.NeedAck]++
	//			if incident != nil && incident.Start.Before(unAckOldestByNotification[notificationName]) && state.NeedAck {
	//				unAckOldestByNotification[notificationName] = incident.Start
	//			}
	//		}
	//		severity := state.CurrentStatus.String()
	//		lastAbnormal := state.LastAbnormalStatus.String()
	//		severityCounts[state.Alert][severity]++
	//		abnormalCounts[state.Alert][lastAbnormal]++
	//		ackStatusCounts[state.Alert][state.NeedAck]++
	//		activeStatusCounts[state.Alert][state.IsActive()]++
	//	}
	for notification := range ackByNotificationCounts {
		ts := opentsdb.TagSet{"notification": notification}
		err := collect.Put("alerts.acknowledgement_status_by_notification",
			ts.Copy().Merge(opentsdb.TagSet{"status": "unacknowledged"}),
			ackByNotificationCounts[notification][true])
		if err != nil {
			slog.Errorln(err)
		}
		err = collect.Put("alerts.acknowledgement_status_by_notification",
			ts.Copy().Merge(opentsdb.TagSet{"status": "acknowledged"}),
			ackByNotificationCounts[notification][false])
		if err != nil {
			slog.Errorln(err)
		}
	}
	for notification, timeStamp := range unAckOldestByNotification {
		ts := opentsdb.TagSet{"notification": notification}
		var ago time.Duration
		if !timeStamp.Equal(time.Unix(1<<63-62135596801, 999999999)) {
			ago = utcNow().Sub(timeStamp)
		}
		err := collect.Put("alerts.oldest_unacked_by_notification",
			ts,
			ago.Seconds())
		if err != nil {
			slog.Errorln(err)
		}
	}
	for alertName := range severityCounts {
		ts := opentsdb.TagSet{"alert": alertName}
		// The tagset of the alert is not included because there is no way to
		// store the string of a group in OpenTSBD in a parsable way. This is
		// because any delimiter we chose could also be part of a tag key or tag
		// value.
		for severity := range severityCounts[alertName] {
			err := collect.Put("alerts.current_severity",
				ts.Copy().Merge(opentsdb.TagSet{"severity": severity}),
				severityCounts[alertName][severity])
			if err != nil {
				slog.Errorln(err)
			}
			err = collect.Put("alerts.last_abnormal_severity",
				ts.Copy().Merge(opentsdb.TagSet{"severity": severity}),
				abnormalCounts[alertName][severity])
			if err != nil {
				slog.Errorln(err)
			}
		}
		err := collect.Put("alerts.acknowledgement_status",
			ts.Copy().Merge(opentsdb.TagSet{"status": "unacknowledged"}),
			ackStatusCounts[alertName][true])
		err = collect.Put("alerts.acknowledgement_status",
			ts.Copy().Merge(opentsdb.TagSet{"status": "acknowledged"}),
			ackStatusCounts[alertName][false])
		if err != nil {
			slog.Errorln(err)
		}
		err = collect.Put("alerts.active_status",
			ts.Copy().Merge(opentsdb.TagSet{"status": "active"}),
			activeStatusCounts[alertName][true])
		if err != nil {
			slog.Errorln(err)
		}
		err = collect.Put("alerts.active_status",
			ts.Copy().Merge(opentsdb.TagSet{"status": "inactive"}),
			activeStatusCounts[alertName][false])
		if err != nil {
			slog.Errorln(err)
		}
	}
}
Exemple #18
0
func c_cisco_ios(host, community string, cpuIntegrator tsIntegrator) (opentsdb.MultiDataPoint, error) {
	var md opentsdb.MultiDataPoint
	ts := opentsdb.TagSet{"host": host}
	// CPU
	if err := ciscoCPU(host, community, ts, cpuIntegrator, &md); err != nil {
		return md, err
	}
	// ÎMemory
	memRaw, err := snmp_subtree(host, community, ciscoBaseOID+ciscoMemoryPoolTable)
	if err != nil {
		return md, fmt.Errorf("failed to get ciscoMemoryPoolTable for host %v: %v", host, err)
	}
	idToPoolEntry := make(map[string]*ciscoMemoryPoolEntry)
	for id, value := range memRaw {
		sp := strings.SplitN(id, ".", 2)
		if len(sp) != 2 {
			slog.Errorln("unexpected length of snmp sub OID (%v) for ciscoMemoryPoolTable for host %v: %v", id, host)
		}
		columnID := sp[0]
		entryID := sp[1]
		if _, ok := idToPoolEntry[entryID]; !ok {
			idToPoolEntry[entryID] = &ciscoMemoryPoolEntry{}
		}
		switch columnID {
		case "2":
			if v, ok := value.([]byte); ok {
				if m, ok := idToPoolEntry[entryID]; ok {
					m.PoolType = string(v)
				} else {
					slog.Errorf("failed to find cisco memory pool entry for entry id %v on host %v for memory pool type", entryID, host)
				}
			} else {
				slog.Errorf("failed to convert memory pool label %v to []byte for host %v", value, host)
			}
		case "5":
			if v, ok := value.(int64); ok {
				if m, ok := idToPoolEntry[entryID]; ok {
					m.Used = v
				} else {
					slog.Errorf("failed to find cisco memory pool entry for entry id %v on host %v for used memory", entryID, host)
				}
			} else {
				slog.Errorf("failed to convert used memory value %v to int64 for host %v", value, host)
			}
		case "6":
			if v, ok := value.(int64); ok {
				if m, ok := idToPoolEntry[entryID]; ok {
					m.Free = v
				} else {
					slog.Errorf("failed to find cisco memory pool entry for entry id %v on host %v for free memory", entryID, host)
				}
			} else {
				slog.Errorf("failed to convert used memory value %v to int64 for host %v", value, host)
			}
		}
	}
	var totalFreeMem int64
	var totalUsedMem int64
	for _, entry := range idToPoolEntry {
		ts := ts.Copy().Merge(opentsdb.TagSet{"name": entry.PoolType})
		Add(&md, "cisco.mem.used", entry.Used, ts, metadata.Gauge, metadata.Bytes, ciscoMemoryPoolUsedDesc)
		Add(&md, "cisco.mem.free", entry.Free, ts, metadata.Gauge, metadata.Bytes, ciscoMemoryPoolFreeDesc)
		totalFreeMem += entry.Free
		totalUsedMem += entry.Used
	}
	Add(&md, osMemFree, totalFreeMem, ts, metadata.Gauge, metadata.Bytes, osMemFreeDesc)
	Add(&md, osMemUsed, totalUsedMem, ts, metadata.Gauge, metadata.Bytes, osMemUsedDesc)
	totalMem := totalFreeMem + totalUsedMem
	Add(&md, osMemTotal, totalMem, ts, metadata.Gauge, metadata.Bytes, osMemTotalDesc)
	Add(&md, osMemPctFree, int64(float64(totalFreeMem)/float64(totalMem)*100), ts, metadata.Gauge, metadata.Pct, osMemPctFreeDesc)
	return md, nil
}
Exemple #19
0
func (c *Conf) loadLookup(s *parse.SectionNode) {
	name := s.Name.Text
	if _, ok := c.Lookups[name]; ok {
		c.errorf("duplicate lookup name: %s", name)
	}
	l := Lookup{
		Name: name,
	}
	l.Text = s.RawText
	var lookupTags opentsdb.TagSet
	saw := make(map[string]bool)
	for _, n := range s.Nodes.Nodes {
		c.at(n)
		switch n := n.(type) {
		case *parse.SectionNode:
			if n.SectionType.Text != "entry" {
				c.errorf("unexpected subsection type")
			}
			tags, err := opentsdb.ParseTags(n.Name.Text)
			if tags == nil && err != nil {
				c.error(err)
			}
			if _, ok := saw[tags.String()]; ok {
				c.errorf("duplicate entry")
			}
			saw[tags.String()] = true
			if len(tags) == 0 {
				c.errorf("lookup entries require tags")
			}
			empty := make(opentsdb.TagSet)
			for k := range tags {
				empty[k] = ""
			}
			if len(lookupTags) == 0 {
				lookupTags = empty
				for k := range empty {
					l.Tags = append(l.Tags, k)
				}
			} else if !lookupTags.Equal(empty) {
				c.errorf("lookup tags mismatch, expected %v", lookupTags)
			}
			e := Entry{
				Def:  n.RawText,
				Name: n.Name.Text,
				ExprEntry: &ExprEntry{
					AlertKey: models.NewAlertKey("", tags),
					Values:   make(map[string]string),
				},
			}
			for _, en := range n.Nodes.Nodes {
				c.at(en)
				switch en := en.(type) {
				case *parse.PairNode:
					e.Values[en.Key.Text] = en.Val.Text
				default:
					c.errorf("unexpected node")
				}
			}
			l.Entries = append(l.Entries, &e)
		default:
			c.errorf("unexpected node")
		}
	}
	c.at(s)
	c.Lookups[name] = &l
}
Exemple #20
0
func (to *TagOverride) ApplyTags(t opentsdb.TagSet) {
	if to.tags != nil {
		t = t.Merge(to.tags)
	}
}
Exemple #21
0
func (s *Schedule) Host(filter string) (map[string]*HostData, error) {
	timeFilterAge := time.Hour * 2 * 24
	hosts := make(map[string]*HostData)
	allHosts, err := s.Search.TagValuesByTagKey("host", timeFilterAge)
	if err != nil {
		return nil, err
	}
	for _, h := range allHosts {
		hosts[h] = newHostData()
	}
	states := s.GetOpenStates()
	silences := s.Silenced()
	// These are all fetched by metric since that is how we store it in redis,
	// so this makes for the fastest response
	tagsByKey := func(metric, hostKey string) (map[string][]opentsdb.TagSet, error) {
		byKey := make(map[string][]opentsdb.TagSet)
		tags, err := s.Search.FilteredTagSets(metric, nil)
		if err != nil {
			return byKey, err
		}
		for _, ts := range tags {
			if host, ok := ts[hostKey]; ok {
				// Make sure the host exists based on our time filter
				if _, ok := hosts[host]; ok {
					byKey[host] = append(byKey[host], ts)
				}
			}
		}
		return byKey, nil
	}
	oldTimestamp := time.Now().Add(-timeFilterAge).Unix()
	oldOrErr := func(ts int64, err error) bool {
		if ts < oldTimestamp || err != nil {
			return true
		}
		return false
	}
	osNetBytesTags, err := tagsByKey("os.net.bytes", "host")
	if err != nil {
		return nil, err
	}
	osNetVirtualBytesTags, err := tagsByKey("os.net.virtual.bytes", "host")
	if err != nil {
		return nil, err
	}
	osNetBondBytesTags, err := tagsByKey("os.net.bond.bytes", "host")
	if err != nil {
		return nil, err
	}
	osNetTunnelBytesTags, err := tagsByKey("os.net.tunnel.bytes", "host")
	if err != nil {
		return nil, err
	}
	osNetOtherBytesTags, err := tagsByKey("os.net.other.bytes", "host")
	if err != nil {
		return nil, err
	}
	osNetIfSpeedTags, err := tagsByKey("os.net.ifspeed", "host")
	if err != nil {
		return nil, err
	}
	osNetVirtualIfSpeedTags, err := tagsByKey("os.net.virtual.ifspeed", "host")
	if err != nil {
		return nil, err
	}
	osNetBondIfSpeedTags, err := tagsByKey("os.net.bond.ifspeed", "host")
	if err != nil {
		return nil, err
	}
	osNetTunnelIfSpeedTags, err := tagsByKey("os.net.tunnel.ifspeed", "host")
	if err != nil {
		return nil, err
	}
	osNetOtherIfSpeedTags, err := tagsByKey("os.net.other.ifspeed", "host")
	if err != nil {
		return nil, err
	}
	hwChassisTags, err := tagsByKey("hw.chassis", "host")
	if err != nil {
		return nil, err
	}
	hwPhysicalDiskTags, err := tagsByKey("hw.storage.pdisk", "host")
	if err != nil {
		return nil, err
	}
	hwVirtualDiskTags, err := tagsByKey("hw.storage.vdisk", "host")
	if err != nil {
		return nil, err
	}
	hwControllersTags, err := tagsByKey("hw.storage.controller", "host")
	if err != nil {
		return nil, err
	}
	hwBatteriesTags, err := tagsByKey("hw.storage.battery", "host")
	if err != nil {
		return nil, err
	}
	hwPowerSuppliesTags, err := tagsByKey("hw.ps", "host")
	if err != nil {
		return nil, err
	}
	hwTempsTags, err := tagsByKey("hw.chassis.temps.reading", "host")
	if err != nil {
		return nil, err
	}
	hwBoardPowerTags, err := tagsByKey("hw.chassis.power.reading", "host")
	if err != nil {
		return nil, err
	}
	diskTags, err := tagsByKey("os.disk.fs.space_total", "host")
	if err != nil {
		return nil, err
	}
	serviceTags, err := tagsByKey("os.service.running", "host")
	if err != nil {
		return nil, err
	}
	// Will assume the same tagsets exist .mem_real, .mem_virtual and possibly .count
	processTags, err := tagsByKey("os.proc.cpu", "host")
	if err != nil {
		return nil, err
	}
	// Will make the assumption that the metric bosun.ping.timeout, resolved, and rtt
	// all share the same tagset
	icmpTimeOutTags, err := tagsByKey("bosun.ping.timeout", "dst_host")
	if err != nil {
		return nil, err
	}
	for name, host := range hosts {
		host.Name = name
		hostTagSet := opentsdb.TagSet{"host": host.Name}
		hostMetadata, err := s.GetMetadata("", hostTagSet)
		if err != nil {
			slog.Error(err)
		}
		processHostIncidents(host, states, silences)
		for _, ts := range icmpTimeOutTags[host.Name] {
			// The host tag represents the polling source for these set of metrics
			source, ok := ts["host"]
			if !ok {
				slog.Errorf("couldn't find source tag for icmp data for host %s", host.Name)
			}
			// 1 Means it timed out
			timeout, timestamp, err := s.Search.GetLast("bosun.ping.timeout", ts.String(), false)
			if oldOrErr(timestamp, err) {
				continue
			}
			rtt, rttTimestamp, _ := s.Search.GetLast("bosun.ping.rtt", ts.String(), false)
			// 1 means dns resolution was successful
			dnsLookup, dnsTimestamp, dnsErr := s.Search.GetLast("bosun.ping.resolved", ts.String(), false)
			host.ICMPData[source] = &ICMPData{
				TimedOut:               timeout == 1 && err == nil,
				TimedOutLastUpdated:    timestamp,
				DNSResolved:            dnsLookup == 1 && dnsErr == nil,
				DNSResolvedLastUpdated: dnsTimestamp,
				RTTMS:          rtt,
				RTTLastUpdated: rttTimestamp,
			}

		}
		for _, ts := range serviceTags[host.Name] {
			name, ok := ts["name"]
			if !ok {
				slog.Errorf("couldn't find service name tag %s for host %s", name, host.Name)
				continue
			}
			fstatus, timestamp, err := s.Search.GetLast("os.service.running", ts.String(), false)
			running := false
			if fstatus != 0 {
				running = true
			}
			if !oldOrErr(timestamp, err) {
				host.Services[name] = &ServiceStatus{
					Running:            running,
					RunningLastUpdated: timestamp,
				}
			}
		}
		for _, ts := range processTags[host.Name] {
			name, ok := ts["name"]
			if !ok {
				slog.Errorf("couldn't find process name tag %s for host %s", name, host.Name)
				continue
			}
			p := &Process{}
			p.CPUPercentUsed, p.CPUPercentLastUpdated, err = s.Search.GetLast("os.proc.cpu", ts.String(), true)
			if oldOrErr(p.CPUPercentLastUpdated, err) {
				continue
			}
			p.UsedRealBytes, p.UsedRealBytesLastUpdated, _ = s.Search.GetLastInt64("os.proc.mem.real", ts.String(), false)
			p.UsedVirtualBytes, p.UsedVirtualBytesLastUpdated, _ = s.Search.GetLastInt64("os.proc.mem.virtual", ts.String(), false)
			p.Count, p.CountLastUpdated, _ = s.Search.GetLastInt64("os.proc.count", ts.String(), false)
			host.Processes[name] = p
		}
		// Process Hardware Chassis States
		for _, ts := range hwChassisTags[host.Name] {
			component, ok := ts["component"]
			if !ok {
				return nil, fmt.Errorf("couldn't find component tag for host %s", host.Name)
			}
			fstatus, timestamp, err := s.Search.GetLast("hw.chassis", ts.String(), false)
			if !oldOrErr(timestamp, err) {
				host.Hardware.ChassisComponents[component] = &ChassisComponent{
					Status:            statusString(int64(fstatus), 0, "Ok", "Bad"),
					StatusLastUpdated: timestamp,
				}
			}
		}
		for _, ts := range hwTempsTags[host.Name] {
			name, ok := ts["name"]
			if !ok {
				slog.Errorf("couldn't find name tag %s for host %s", name, host.Name)
			}
			t := &Temp{}
			var tStatus float64
			tStatus, t.StatusLastUpdated, err = s.Search.GetLast("hw.chassis.temps", ts.String(), false)
			t.Celsius, t.CelsiusLastUpdated, _ = s.Search.GetLast("hw.chassis.temps.reading", ts.String(), false)
			if oldOrErr(t.StatusLastUpdated, err) {
				continue
			}
			t.Status = statusString(int64(tStatus), 0, "Ok", "Bad")
			host.Hardware.Temps[name] = t
		}
		for _, ts := range hwPowerSuppliesTags[host.Name] {
			id, ok := ts["id"]
			if !ok {
				return nil, fmt.Errorf("couldn't find power supply tag for host %s", host.Name)
			}
			idPlus, err := strconv.Atoi(id)
			if err != nil {
				slog.Errorf("couldn't conver it do integer for power supply id %s", id)
			}
			idPlus++
			ps := &PowerSupply{}
			fstatus, timestamp, err := s.Search.GetLast("hw.ps", ts.String(), false)
			ps.Amps, ps.AmpsLastUpdated, _ = s.Search.GetLast("hw.chassis.current.reading", opentsdb.TagSet{"host": host.Name, "id": fmt.Sprintf("PS%v", idPlus)}.String(), false)
			ps.Volts, ps.VoltsLastUpdated, _ = s.Search.GetLast("hw.chassis.volts.reading", opentsdb.TagSet{"host": host.Name, "name": fmt.Sprintf("PS%v_Voltage_%v", idPlus, idPlus)}.String(), false)
			if oldOrErr(timestamp, err) {
				continue
			}
			ps.Status = statusString(int64(fstatus), 0, "Ok", "Bad")
			host.Hardware.PowerSupplies[id] = ps
			for _, m := range hostMetadata {
				if m.Name != "psMeta" || m.Time.Before(time.Now().Add(-timeFilterAge)) || !m.Tags.Equal(ts) {
					continue
				}
				if val, ok := m.Value.(string); ok {
					err = json.Unmarshal([]byte(val), &ps)
					if err != nil {
						slog.Errorf("error unmarshalling power supply meta for host %s, while generating host api: %s", host.Name, err)
					} else {
						host.Hardware.PowerSupplies[id] = ps
					}
				}
			}
		}
		for _, ts := range hwBatteriesTags[host.Name] {
			id, ok := ts["id"]
			if !ok {
				slog.Errorf("couldn't find battery id tag %s for host %s", id, host.Name)
				continue
			}
			fstatus, timestamp, err := s.Search.GetLast("hw.storage.battery", ts.String(), false)
			if !oldOrErr(timestamp, err) {
				host.Hardware.Storage.Batteries[id] = &Battery{
					Status:            statusString(int64(fstatus), 0, "Ok", "Bad"),
					StatusLastUpdated: timestamp,
				}
			}
		}
		for _, ts := range hwBoardPowerTags[host.Name] {
			fstatus, timestamp, err := s.Search.GetLast("hw.chassis.power.reading", ts.String(), false)
			if !oldOrErr(timestamp, err) {
				host.Hardware.BoardPowerReading = &BoardPowerReading{
					Watts:            int64(fstatus),
					WattsLastUpdated: timestamp,
				}
			}
		}
		for _, ts := range hwPhysicalDiskTags[host.Name] {
			id, ok := ts["id"]
			if !ok {
				return nil, fmt.Errorf("couldn't find physical disk id tag for host %s", host.Name)
			}
			pd := &PhysicalDisk{}
			fstatus, timestamp, err := s.Search.GetLast("hw.storage.pdisk", ts.String(), false)
			if !oldOrErr(timestamp, err) {
				pd.Status = statusString(int64(fstatus), 0, "Ok", "Bad")
				pd.StatusLastUpdated = timestamp
				host.Hardware.Storage.PhysicalDisks[id] = pd
			}
			for _, m := range hostMetadata {
				if m.Name != "physicalDiskMeta" || m.Time.Before(time.Now().Add(-timeFilterAge)) || !m.Tags.Equal(ts) {
					continue
				}
				if val, ok := m.Value.(string); ok {
					err = json.Unmarshal([]byte(val), &pd)
					if err != nil {
						slog.Errorf("error unmarshalling addresses for host %s, interface %s while generating host api: %s", host.Name, m.Tags["iface"], err)
					} else {
						host.Hardware.Storage.PhysicalDisks[id] = pd
					}
				}
			}
		}
		for _, ts := range hwVirtualDiskTags[host.Name] {
			id, ok := ts["id"]
			if !ok {
				return nil, fmt.Errorf("couldn't find virtual disk id tag for host %s", host.Name)
			}
			fstatus, timestamp, err := s.Search.GetLast("hw.storage.vdisk", ts.String(), false)
			if !oldOrErr(timestamp, err) {
				host.Hardware.Storage.VirtualDisks[id] = &VirtualDisk{
					Status:            statusString(int64(fstatus), 0, "Ok", "Bad"),
					StatusLastUpdated: timestamp,
				}
			}
		}
		for _, ts := range hwControllersTags[host.Name] {
			id, ok := ts["id"]
			if !ok {
				return nil, fmt.Errorf("couldn't find controller id tag for host %s", host.Name)
			}
			fstatus, timestamp, err := s.Search.GetLast("hw.storage.controller", ts.String(), false)
			c := &Controller{}
			if !oldOrErr(timestamp, err) {
				c.Status = statusString(int64(fstatus), 0, "Ok", "Bad")
				c.StatusLastUpdated = timestamp
				host.Hardware.Storage.Controllers[id] = c
			}
			for _, m := range hostMetadata {
				if m.Name != "controllerMeta" || m.Time.Before(time.Now().Add(-timeFilterAge)) || !m.Tags.Equal(ts) {
					continue
				}
				if val, ok := m.Value.(string); ok {
					err = json.Unmarshal([]byte(val), &c)
					if err != nil {
						slog.Errorf("error unmarshalling controller meta for host %s: %s", host.Name, err)
					} else {
						host.Hardware.Storage.Controllers[id] = c
					}
				}
			}
		}
		for _, ts := range diskTags[host.Name] {
			disk, ok := ts["disk"]
			if !ok {
				return nil, fmt.Errorf("couldn't find disk tag for host %s", host.Name)
			}
			d := &Disk{}
			d.TotalBytes, d.StatsLastUpdated, err = s.Search.GetLastInt64("os.disk.fs.space_total", ts.String(), false)
			d.UsedBytes, _, _ = s.Search.GetLastInt64("os.disk.fs.space_used", ts.String(), false)
			if oldOrErr(d.StatsLastUpdated, err) {
				continue
			}
			host.Disks[disk] = d
			for _, m := range hostMetadata {
				if m.Name != "label" || m.Time.Before(time.Now().Add(-timeFilterAge)) || !m.Tags.Equal(ts) {
					continue
				}
				if label, ok := m.Value.(string); ok {
					host.Disks[disk].Label = label
					break
				}
			}
		}
		// Get CPU, Memory, Uptime
		var timestamp int64
		var cpu float64
		if cpu, timestamp, err = s.Search.GetLast("os.cpu", hostTagSet.String(), true); err != nil {
			cpu, timestamp, _ = s.Search.GetLast("cisco.cpu", hostTagSet.String(), false)
		}
		host.CPU.PercentUsed = cpu
		host.CPU.StatsLastUpdated = timestamp
		host.Memory.TotalBytes, host.Memory.StatsLastUpdated, _ = s.Search.GetLast("os.mem.total", hostTagSet.String(), false)
		host.Memory.UsedBytes, _, _ = s.Search.GetLast("os.mem.used", hostTagSet.String(), false)
		host.UptimeSeconds, _, _ = s.Search.GetLastInt64("os.system.uptime", hostTagSet.String(), false)
		for _, m := range hostMetadata {
			if m.Time.Before(time.Now().Add(-timeFilterAge)) {
				continue
			}
			var iface *HostInterface
			if name := m.Tags["iface"]; name != "" {
				if host.Interfaces[name] == nil {
					h := new(HostInterface)
					host.Interfaces[name] = h
				}
				iface = host.Interfaces[name]
			}
			if name := m.Tags["iname"]; name != "" && iface != nil {
				iface.Name = name
			}
			switch val := m.Value.(type) {
			case string:
				switch m.Name {
				case "addresses":
					if iface != nil {
						addresses := []string{}
						err = json.Unmarshal([]byte(val), &addresses)
						if err != nil {
							slog.Errorf("error unmarshalling addresses for host %s, interface %s while generating host api: %s", host.Name, m.Tags["iface"], err)
						}
						for _, address := range addresses {
							iface.IPAddresses = append(iface.IPAddresses, address)
						}
					}
				case "cdpCacheEntries":
					if iface != nil {
						var cdpCacheEntries CDPCacheEntries
						err = json.Unmarshal([]byte(val), &cdpCacheEntries)
						if err != nil {
							slog.Errorf("error unmarshalling cdpCacheEntries for host %s, interface %s while generating host api: %s", host.Name, m.Tags["iface"], err)
						} else {
							iface.CDPCacheEntries = cdpCacheEntries
						}
					}
				case "remoteMacs":
					if iface != nil {
						remoteMacs := []string{}
						err = json.Unmarshal([]byte(val), &remoteMacs)
						if err != nil {
							slog.Errorf("error unmarshalling remoteMacs for host %s, interface %s while generating host api: %s", host.Name, m.Tags["iface"], err)
						} else {
							iface.RemoteMacs = remoteMacs
						}
					}
				case "description", "alias":
					if iface != nil {
						iface.Description = val
					}
				case "dataStores":
					dataStores := []string{}
					err = json.Unmarshal([]byte(val), &dataStores)
					if err != nil {
						slog.Errorf("error unmarshalling datastores for host %s while generating host api: %s", host.Name, err)
					}
					for _, dataStore := range dataStores {
						tags := opentsdb.TagSet{"disk": dataStore}.String()
						total, totalTs, totalErr := s.Search.GetLastInt64("vsphere.disk.space_total", tags, false)
						used, usedTs, usedErr := s.Search.GetLastInt64("vsphere.disk.space_used", tags, false)
						if totalErr != nil || usedErr != nil || totalTs < 1 || usedTs < 1 {
							continue
						}
						host.Disks[dataStore] = &Disk{
							TotalBytes: total,
							UsedBytes:  used,
						}
					}
				case "mac":
					if iface != nil {
						iface.MAC = val
					}
				case "manufacturer":
					host.Manufacturer = val
				case "master":
					if iface != nil {
						iface.Master = val
					}
				case "memory":
					if name := m.Tags["name"]; name != "" {
						fstatus, timestamp, err := s.Search.GetLast("hw.chassis.memory", opentsdb.TagSet{"host": host.Name, "name": name}.String(), false)
						// Status code uses the severity function in collectors/dell_hw.go. That is a binary
						// state that is 0 for non-critical or Ok. Todo would be to update this with more
						// complete status codes when HW collector is refactored and we have something to
						// clean out addr entries from the tagset metadata db
						host.Hardware.Memory[name] = &MemoryModule{
							StatusLastUpdated: timestamp,
							Size:              val,
						}
						// Only set if we have a value
						if err == nil && timestamp > 0 {
							host.Hardware.Memory[name].Status = statusString(int64(fstatus), 0, "Ok", "Bad")
						}
					}
				case "hypervisor":
					host.VM = &VM{}
					host.VM.Host = val
					powerstate, timestamp, err := s.Search.GetLast("vsphere.guest.powered_state", opentsdb.TagSet{"guest": host.Name}.String(), false)
					if timestamp > 0 && err != nil {
						switch int64(powerstate) {
						case 0:
							host.VM.PowerState = "poweredOn"
						case 1:
							host.VM.PowerState = "poweredOff"
						case 2:
							host.VM.PowerState = "suspended"
						}
						host.VM.PowerStateLastUpdated = timestamp
					}
					if hostsHost, ok := hosts[val]; ok {
						hostsHost.Guests = append(hostsHost.Guests, host.Name)
					}
				case "model":
					host.Model = val
				case "name":
					if iface != nil {
						iface.Name = val
					}
				case "processor":
					if name := m.Tags["name"]; name != "" {
						host.CPU.Processors[name] = val
					}
				case "serialNumber":
					host.SerialNumber = val
				case "version":
					host.OS.Version = val
				case "versionCaption", "uname":
					host.OS.Caption = val
				}
			case float64:
				switch m.Name {
				case "speed":
					if iface != nil {
						iface.LinkSpeed = int64(val)
					}
				}
			}
		}
		GetIfaceBits := func(netType string, ifaceId string, iface *HostInterface, host string, tags []opentsdb.TagSet) error {
			metric := "os.net." + netType + ".bytes"
			if netType == "" {
				metric = "os.net.bytes"
			}
			for _, ts := range tags {
				if ts["iface"] != ifaceId {
					continue
				}
				dir, ok := ts["direction"]
				if !ok {
					continue
				}
				val, timestamp, _ := s.Search.GetLastInt64(metric, ts.String(), true)
				if dir == "in" {
					iface.Inbps = val * 8
				}
				if dir == "out" {
					iface.Outbps = val * 8
				}
				iface.StatsLastUpdated = timestamp
				iface.Type = netType
			}
			return nil
		}
		GetIfaceSpeed := func(netType string, ifaceId string, iface *HostInterface, host string, tags []opentsdb.TagSet) error {
			metric := "os.net." + netType + ".ifspeed"
			if netType == "" {
				metric = "os.net.ifspeed"
			}
			for _, ts := range tags {
				if ts["iface"] != ifaceId {
					continue
				}
				val, timestamp, err := s.Search.GetLastInt64(metric, ts.String(), false)
				if !oldOrErr(timestamp, err) {
					iface.LinkSpeed = val
				}
			}
			return nil
		}
		for ifaceId, iface := range host.Interfaces {
			if err := GetIfaceBits("", ifaceId, iface, host.Name, osNetBytesTags[host.Name]); err != nil {
				return nil, err
			}
			if err := GetIfaceBits("virtual", ifaceId, iface, host.Name, osNetVirtualBytesTags[host.Name]); err != nil {
				return nil, err
			}
			if err := GetIfaceBits("bond", ifaceId, iface, host.Name, osNetBondBytesTags[host.Name]); err != nil {
				return nil, err
			}
			if err := GetIfaceBits("tunnel", ifaceId, iface, host.Name, osNetTunnelBytesTags[host.Name]); err != nil {
				return nil, err
			}
			if err := GetIfaceBits("other", ifaceId, iface, host.Name, osNetOtherBytesTags[host.Name]); err != nil {
				return nil, err
			}
			if err := GetIfaceSpeed("", ifaceId, iface, host.Name, osNetIfSpeedTags[host.Name]); err != nil {
				return nil, err
			}
			if err := GetIfaceSpeed("virtual", ifaceId, iface, host.Name, osNetVirtualIfSpeedTags[host.Name]); err != nil {
				return nil, err
			}
			if err := GetIfaceSpeed("bond", ifaceId, iface, host.Name, osNetBondIfSpeedTags[host.Name]); err != nil {
				return nil, err
			}
			if err := GetIfaceSpeed("tunnel", ifaceId, iface, host.Name, osNetTunnelIfSpeedTags[host.Name]); err != nil {
				return nil, err
			}
			if err := GetIfaceSpeed("other", ifaceId, iface, host.Name, osNetOtherIfSpeedTags[host.Name]); err != nil {
				return nil, err
			}
		}
		host.Clean()
	}
	return hosts, nil
}
Exemple #22
0
func DatabaseParseResults(c conf.Database, query *DatabaseQuery, results *[][]string) (opentsdb.MultiDataPoint, error) {
	if len(*results) < 1 {
		return nil, nil
	}

	numTagLoops := len((*results)[0]) - 1
	if query.hasTime {
		numTagLoops--
	}
	if numTagLoops < 0 {
		return nil, fmt.Errorf("invalid number of columns")
	}
	numTagLoops = (numTagLoops - (numTagLoops % 2)) / 2

	var md opentsdb.MultiDataPoint
	var tagName string
	var tagValue string
	var tagsBase opentsdb.TagSet
	baseName := c.Type + "."
	if c.DBName == "" {
		tagsBase = opentsdb.TagSet{"inst_id": strconv.Itoa(c.InstId)}
	} else {
		tagsBase = opentsdb.TagSet{"db_name": c.DBName, "inst_id": strconv.Itoa(c.InstId)}
	}

	for _, result := range *results {
		if result[0] == "" {
			continue
		}

		// Check result[0] is vaild metric value?

		tags := tagsBase.Copy()
		for i := 0; i < numTagLoops; i++ {
			if query.hasTime {
				tagName = strings.Replace(result[(i*2)+2], " ", "_", -1)
				tagValue = strings.Replace(result[(i*2)+3], " ", "_", -1)
			} else {
				tagName = strings.Replace(result[(i*2)+1], " ", "_", -1)
				tagValue = strings.Replace(result[(i*2)+2], " ", "_", -1)
			}
			tagName, _ = opentsdb.Clean(tagName)
			tagValue, _ = opentsdb.Clean(tagValue)
			tagName = ContinuousCollectorVars.reTwoOrMoreUnderscore.ReplaceAllString(tagName, "_")
			tagValue = ContinuousCollectorVars.reTwoOrMoreUnderscore.ReplaceAllString(tagValue, "_")

			if tagName == "" || tagValue == "" {
				continue
			}
			tags = tags.Merge(opentsdb.TagSet{tagName: tagValue})
		}

		// Add metadata tag set type to configuration file?

		if query.hasTime {
			timestamp, _ := strconv.ParseInt(result[1], 10, 64)
			if timestamp < 1 {
				return nil, fmt.Errorf("invalid timestamp")
			}
			AddTS(&md, baseName+query.name, timestamp, result[0], tags, metadata.Unknown, metadata.None, query.description)
		} else {
			Add(&md, baseName+query.name, result[0], tags, metadata.Unknown, metadata.None, query.description)
		}
	}

	return md, nil
}
Exemple #23
0
// CollectStates sends various state information to bosun with collect.
func (s *Schedule) CollectStates() {
	// [AlertName][Severity]Count
	severityCounts := make(map[string]map[string]int64)
	abnormalCounts := make(map[string]map[string]int64)
	ackStatusCounts := make(map[string]map[bool]int64)
	activeStatusCounts := make(map[string]map[bool]int64)
	// Initalize the Counts
	for _, alert := range s.Conf.Alerts {
		severityCounts[alert.Name] = make(map[string]int64)
		abnormalCounts[alert.Name] = make(map[string]int64)
		var i Status
		for i = 1; i.String() != "none"; i++ {
			severityCounts[alert.Name][i.String()] = 0
			abnormalCounts[alert.Name][i.String()] = 0
		}
		ackStatusCounts[alert.Name] = make(map[bool]int64)
		activeStatusCounts[alert.Name] = make(map[bool]int64)
		ackStatusCounts[alert.Name][false] = 0
		activeStatusCounts[alert.Name][false] = 0
		ackStatusCounts[alert.Name][true] = 0
		activeStatusCounts[alert.Name][true] = 0
	}
	for _, state := range s.status {
		if !state.Open {
			continue
		}
		severity := state.Status().String()
		lastAbnormal := state.AbnormalStatus().String()
		severityCounts[state.Alert][severity]++
		abnormalCounts[state.Alert][lastAbnormal]++
		ackStatusCounts[state.Alert][state.NeedAck]++
		activeStatusCounts[state.Alert][state.IsActive()]++
	}
	for alertName := range severityCounts {
		ts := opentsdb.TagSet{"alert": alertName}
		// The tagset of the alert is not included because there is no way to
		// store the string of a group in OpenTSBD in a parsable way. This is
		// because any delimiter we chose could also be part of a tag key or tag
		// value.
		for severity := range severityCounts[alertName] {
			err := collect.Put("alerts.current_severity",
				ts.Copy().Merge(opentsdb.TagSet{"severity": severity}),
				severityCounts[alertName][severity])
			if err != nil {
				slog.Errorln(err)
			}
			err = collect.Put("alerts.last_abnormal_severity",
				ts.Copy().Merge(opentsdb.TagSet{"severity": severity}),
				abnormalCounts[alertName][severity])
			if err != nil {
				slog.Errorln(err)
			}
		}
		err := collect.Put("alerts.acknowledgement_status",
			ts.Copy().Merge(opentsdb.TagSet{"status": "unacknowledged"}),
			ackStatusCounts[alertName][true])
		err = collect.Put("alerts.acknowledgement_status",
			ts.Copy().Merge(opentsdb.TagSet{"status": "acknowledged"}),
			ackStatusCounts[alertName][false])
		if err != nil {
			slog.Errorln(err)
		}
		err = collect.Put("alerts.active_status",
			ts.Copy().Merge(opentsdb.TagSet{"status": "active"}),
			activeStatusCounts[alertName][true])
		if err != nil {
			slog.Errorln(err)
		}
		err = collect.Put("alerts.active_status",
			ts.Copy().Merge(opentsdb.TagSet{"status": "inactive"}),
			activeStatusCounts[alertName][false])
		if err != nil {
			slog.Errorln(err)
		}
	}
}
Exemple #24
0
func c_varnish_unix() (opentsdb.MultiDataPoint, error) {
	var md opentsdb.MultiDataPoint
	const metric = "varnish."

	r, err := util.Command(5*time.Second, nil, "varnishstat", "-j")
	if err != nil {
		return nil, err
	}

	var stats varnishStats
	if err := json.NewDecoder(r).Decode(&stats); err != nil {
		return nil, err
	}

	for name, raw := range stats {
		if name == "timestamp" {
			continue
		}

		var v varnishStat
		if err := json.Unmarshal(raw, &v); err != nil {
			slog.Errorln("varnish parser error:", name, err)
			continue
		}

		ts := opentsdb.TagSet{}

		// special case for backend stats. extract backend name, host and port, put
		// them in tags and remove them in name.
		// the format is like "name(host,,port)" for the "ident" field of "VBE" type
		if v.Type == "VBE" {
			subtype := v.SubType

			name = strings.Replace(name, "."+subtype, "", -1)

			idx := strings.Index(subtype, "(")
			if idx < 0 || len(subtype)-idx < 4 {
				// output format changed, ignore
				continue
			}

			ss := strings.Split(subtype[idx+1:len(subtype)-1], ",")
			if len(ss) != 3 {
				// output format changed, ignore
				continue
			}

			ts.Merge(opentsdb.TagSet{"backend": subtype[:idx]})
			ts.Merge(opentsdb.TagSet{"endpoint": ss[0] + "_" + ss[2]})
		}

		rate := metadata.RateType(metadata.Gauge)
		if flag := v.Flag; flag == "a" || flag == "c" {
			rate = metadata.Counter
		}

		unit := metadata.Unit(metadata.Count)
		if v.Format == "B" {
			unit = metadata.Bytes
		}

		Add(&md, metric+strings.ToLower(name), v.Value, ts, rate, unit, v.Desc)
	}
	return md, nil
}
Exemple #25
0
func rabbitmqMessageStats(p string, ts opentsdb.TagSet, ms rmqMessageStats) opentsdb.MultiDataPoint {
	var md opentsdb.MultiDataPoint
	Add(&md, p+"message_stats", ms.Ack, ts.Copy().Merge(opentsdb.TagSet{"method": "ack"}),
		metadata.Counter, metadata.Message, DescRmqMessageStatsAck)
	Add(&md, p+"message_stats", ms.Confirm, ts.Copy().Merge(opentsdb.TagSet{"method": "confirm"}),
		metadata.Counter, metadata.Message, DescRmqMessageStatsConfirm)
	Add(&md, p+"message_stats", ms.Deliver, ts.Copy().Merge(opentsdb.TagSet{"method": "deliver"}),
		metadata.Counter, metadata.Message, DescRmqMessageStatsDeliver)
	Add(&md, p+"message_stats", ms.DeliverGet, ts.Copy().Merge(opentsdb.TagSet{"method": "deliver_get"}),
		metadata.Counter, metadata.Message, DescRmqMessageStatsDeliverGet)
	Add(&md, p+"message_stats", ms.DeliverNoAck, ts.Copy().Merge(opentsdb.TagSet{"method": "deliver_noack"}),
		metadata.Counter, metadata.Message, DescRmqMessageStatsDeliverNoAck)
	Add(&md, p+"message_stats", ms.Get, ts.Copy().Merge(opentsdb.TagSet{"method": "get"}),
		metadata.Counter, metadata.Message, DescRmqMessageStatsGet)
	Add(&md, p+"message_stats", ms.GetNoAck, ts.Copy().Merge(opentsdb.TagSet{"method": "get_noack"}),
		metadata.Counter, metadata.Message, DescRmqMessageStatsGetNoack)
	Add(&md, p+"message_stats", ms.Publish, ts.Copy().Merge(opentsdb.TagSet{"method": "publish"}),
		metadata.Counter, metadata.Message, DescRmqMessageStatsPublish)
	Add(&md, p+"message_stats", ms.PublishIn, ts.Copy().Merge(opentsdb.TagSet{"method": "publish_in"}),
		metadata.Counter, metadata.Message, DescRmqMessageStatsPublishIn)
	Add(&md, p+"message_stats", ms.PublishOut, ts.Copy().Merge(opentsdb.TagSet{"method": "publish_out"}),
		metadata.Counter, metadata.Message, DescRmqMessageStatsPublishOut)
	Add(&md, p+"message_stats", ms.Redeliver, ts.Copy().Merge(opentsdb.TagSet{"method": "redeliver"}),
		metadata.Counter, metadata.Message, DescRmqMessageStatsRedeliver)
	Add(&md, p+"message_stats", ms.Return, ts.Copy().Merge(opentsdb.TagSet{"method": "return"}),
		metadata.Counter, metadata.Message, DescRmqMessageStatsReturn)
	return md
}
Exemple #26
0
func NewAlertKey(name string, group opentsdb.TagSet) AlertKey {
	return AlertKey(name + group.String())
}
Exemple #27
0
func tagMetaKey(tags opentsdb.TagSet, name string) string {
	return fmt.Sprintf("tmeta:%s:%s", tags.Tags(), name)
}