作者:mathp
项目:bosu
// 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
}
作者:jareks
项目:bosu
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)
} */
}
}
作者:mathp
项目:bosu
func (to *TagOverride) AddTags(t opentsdb.TagSet) {
if to.tags == nil {
to.tags = t.Copy()
} else {
to.tags = to.tags.Merge(t)
}
}
作者:mathp
项目:bosu
// 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
}
作者:harryshayn
项目:bosu
// 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)
}
作者:pd
项目:bosu
// 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
}
作者:pd
项目:bosu
// 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
}
作者:nicolle
项目:bosu
// 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)
}
作者:uro
项目:bosu
// 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
}
作者:pd
项目:bosu
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
}
作者:pd
项目:bosu
// 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
}
作者:eswd
项目:bosu
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
}
作者:noblehn
项目:bosu
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
}
作者:eswd
项目:bosu
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())
}
}
作者:nicolle
项目:bosu
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
}
作者:mathp
项目:bosu
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
}
作者:Skyscanne
项目:bosu
// 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])
//.........这里部分代码省略.........
作者:eswd
项目:bosu
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
}
作者:rajde
项目:bosu
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
}
作者:mathp
项目:bosu
func (to *TagOverride) ApplyTags(t opentsdb.TagSet) {
if to.tags != nil {
t = t.Merge(to.tags)
}
}