func (live Data) genElasticLineWithValue(index, typ, value, timestamp string) string { value = strings.Replace(value, `"`, `\"`, -1) if live.serviceDisplayName == "" { live.serviceDisplayName = config.GetConfig().Elasticsearch.HostcheckAlias } head := fmt.Sprintf(`{"index":{"_index":"%s","_type":"messages"}}`, helper.GenIndex(index, timestamp)) + "\n" data := fmt.Sprintf(`{"timestamp":%s,"message":"%s","author":"%s","host":"%s","service":"%s","type":"%s"}`+"\n", helper.CastStringTimeFromSToMs(timestamp), value, live.author, live.hostName, live.serviceDisplayName, typ, ) return head + data }
//PerformanceDataIterator returns an iterator to loop over generated perf data. func (w *NagiosSpoolfileWorker) PerformanceDataIterator(input map[string]string) <-chan PerformanceData { ch := make(chan PerformanceData) typ := findType(input) if typ == "" { if len(input) > 1 { logging.GetLogger().Info("Line does not match the scheme", input) } close(ch) return ch } currentCommand := w.searchAltCommand(input[typ+"PERFDATA"], input[typ+checkcommand]) currentTime := helper.CastStringTimeFromSToMs(input[timet]) currentService := "" if typ != hostType { currentService = input[servicedesc] } go func() { perfSlice := regexPerformancelable.FindAllStringSubmatch(input[typ+"PERFDATA"], -1) currentCheckMultiLabel := "" //try to find a check_multi prefix if len(perfSlice) > 0 && len(perfSlice[0]) > 1 { currentCheckMultiLabel = getCheckMultiRegexMatch(perfSlice[0][1]) } item: for _, value := range perfSlice { // Allows to add tags and fields to spoolfileentries tag := map[string]string{} if tagString, ok := input[nagfluxTags]; ok { tag = helper.StringToMap(tagString, " ", "=") } field := map[string]string{} if tagString, ok := input[nagfluxField]; ok { field = helper.StringToMap(tagString, " ", "=") } perf := PerformanceData{ hostname: input[hostname], service: currentService, command: currentCommand, time: currentTime, performanceLabel: value[1], unit: value[3], tags: tag, fields: field, } if currentCheckMultiLabel != "" { //if an check_multi prefix was found last time //test if the current one has also one if potentialNextOne := getCheckMultiRegexMatch(perf.performanceLabel); potentialNextOne == "" { // if not put the last one in front the current perf.performanceLabel = currentCheckMultiLabel + perf.performanceLabel } else { // else remember the current prefix for the next one currentCheckMultiLabel = potentialNextOne } } for i, data := range value { if i > 1 && i != 3 && data != "" { performanceType, err := indexToperformanceType(i) if err != nil { logging.GetLogger().Warn(err, value) continue } //Add downtime tag if needed if performanceType == "value" && w.livestatusCacheBuilder.IsServiceInDowntime(perf.hostname, perf.service, input[timet]) { perf.tags["downtime"] = "true" } if performanceType == "warn" || performanceType == "crit" { //Range handling fillLabel := performanceType + "-fill" rangeHits := rangeRegex.FindAllStringSubmatch(data, -1) if len(rangeHits) == 1 { perf.tags[fillLabel] = "none" perf.fields[performanceType] = helper.StringIntToStringFloat(rangeHits[0][0]) } else if len(rangeHits) == 2 { //If there is a range with no infinity as border, create two points if strings.Contains(data, "@") { perf.tags[fillLabel] = "inner" } else { perf.tags[fillLabel] = "outer" } for i, tag := range []string{"min", "max"} { tagKey := fmt.Sprintf("%s-%s", performanceType, tag) perf.fields[tagKey] = helper.StringIntToStringFloat(rangeHits[i][0]) } } else { logging.GetLogger().Warn("Regexmatching went wrong", rangeHits, data, value) } } else { if !helper.IsStringANumber(data) { continue item } perf.fields[performanceType] = helper.StringIntToStringFloat(data) } } } ch <- perf } close(ch) }() return ch }
//Iterator to loop over generated perf data. func (w *NagiosSpoolfileWorker) old_performanceDataIterator(input map[string]string) <-chan PerformanceData { ch := make(chan PerformanceData) var typ string if isHostPerformanceData(input) { typ = hostType } else if isServicePerformanceData(input) { typ = serviceType } else { if len(input) > 1 { logging.GetLogger().Info("Line does not match the scheme", input) } close(ch) return ch } //logging.GetLogger().Info("XX INPUT XX", input) currentHostname := helper.SanitizeInfluxInput(input[hostname]) currentCommand := w.searchAltCommand(input[typ+"PERFDATA"], input[typ+checkcommand]) currentTime := helper.CastStringTimeFromSToMs(input[timet]) currentService := "" if typ != hostType { currentService = helper.SanitizeInfluxInput(input[servicedesc]) } // logging.GetLogger().Info("XX currentHostname XX ", currentHostname) // logging.GetLogger().Info("XX currentCommand XX ", currentCommand) // logging.GetLogger().Info("XX currentTime XX ", currentTime) // logging.GetLogger().Info("XX currentService XX ", currentService) //currentCommand = strings.Replace(currentCommand, "check_mk-", "", -1) go func() { for _, value := range w.regexPerformancelable.FindAllStringSubmatch(input[typ+"PERFDATA"], -1) { perf := PerformanceData{ hostname: currentHostname, service: currentService, command: currentCommand, time: currentTime, performanceLabel: helper.SanitizeInfluxInput(value[1]), unit: helper.SanitizeInfluxInput(value[3]), fieldseperator: w.fieldseperator, tags: map[string]string{}, } for i, data := range value { if i > 1 && i != 3 && data != "" { performanceType, err := indexToperformanceType(i) if err != nil { logging.GetLogger().Warn(err, value) continue } //Add downtime tag if needed if performanceType == "value" && w.livestatusCacheBuilder.IsServiceInDowntime(perf.hostname, perf.service, input[timet]) { perf.tags["downtime"] = "1" } //logging.GetLogger().Info("XX hostname: ",perf.hostname) //logging.GetLogger().Info("XX service: ",perf.service) //logging.GetLogger().Info("XX command: ",perf.command) //logging.GetLogger().Info("XX time: ",perf.time) //logging.GetLogger().Info("XX performanceLabel: ",perf.performanceLabel) //logging.GetLogger().Info("XX performanceType: ",perf.performanceType) //logging.GetLogger().Info("XX unit: ",perf.unit) ////logging.GetLogger().Info("XX tags: ",perf.tags) //for key, value := range perf.tags { //logging.GetLogger().Info("XX tag - ",key , " ",value) ////fmt.Println("Key:", key, "Value:", value) //} if performanceType == "warn" || performanceType == "crit" { //Range handling rangeRegex := regexp.MustCompile(`[\d\.\-]+`) rangeHits := rangeRegex.FindAllStringSubmatch(data, -1) if len(rangeHits) == 1 { perf.tags["fill"] = "none" perf.tags["type"] = performanceType perf.value = helper.StringIntToStringFloat(rangeHits[0][0]) perf.performanceType = performanceType ch <- perf } else if len(rangeHits) == 2 { //If there is a range with no infinity as border, create two points perf.performanceType = performanceType if strings.Contains(data, "@") { perf.tags["fill"] = "inner" } else { perf.tags["fill"] = "outer" } for i, tag := range []string{"min", "max"} { tmpPerf := perf tmpPerf.tags = helper.CopyMap(perf.tags) tmpPerf.tags["type"] = tag tmpPerf.value = helper.StringIntToStringFloat(rangeHits[i][0]) ch <- tmpPerf } } else { logging.GetLogger().Warn("Regexmatching went wrong", rangeHits) } } else { perf.tags["fill"] = "none" perf.tags["type"] = "value" perf.value = helper.StringIntToStringFloat(data) perf.performanceType = performanceType ch <- perf } } } } close(ch) }() return ch }
func TestGenInfluxLine(t *testing.T) { t.Parallel() live := Data{"host", "service", "comment", "0", "author"} expected := fmt.Sprintf("%s%s message=\"%s\" %s", live.getTablename(), ",a=1,b=2,author="+live.author, "comment", helper.CastStringTimeFromSToMs(live.entryTime)) result := live.genInfluxLine(",a=1,b=2") if expected != result { t.Errorf("Expected:%s\nResult:%s", expected, result) } }
//Generates the linedata which can be parsed from influxdb func (live Data) genInfluxLineWithValue(tags, text string) string { tags += ",author=" + live.author return fmt.Sprintf("%s%s message=\"%s\" %s", live.getTablename(), tags, text, helper.CastStringTimeFromSToMs(live.entryTime)) }
//Prints the data in influxdb lineformat func (downtime LivestatusDowntimeData) Print(version float32) string { downtime.sanitizeValues() if version >= 0.9 { tags := ",type=downtime,author=" + downtime.author start := fmt.Sprintf("%s%s value=\"%s\" %s", downtime.getTablename(), tags, strings.TrimSpace("Downtime start: <br>"+downtime.comment), helper.CastStringTimeFromSToMs(downtime.entry_time)) end := fmt.Sprintf("%s%s value=\"%s\" %s", downtime.getTablename(), tags, strings.TrimSpace("Downtime end: <br>"+downtime.comment), helper.CastStringTimeFromSToMs(downtime.end_time)) return start + "\n" + end } else { logging.GetLogger().Fatalf("This influxversion [%f] given in the config is not supportet", version) return "" } }
//PrintForInfluxDB prints the data in influxdb lineformat func (downtime DowntimeData) PrintForInfluxDB(version string) string { downtime.sanitizeValues() if helper.VersionOrdinal(version) >= helper.VersionOrdinal("0.9") { tags := ",type=downtime,author=" + downtime.author start := fmt.Sprintf("%s%s message=\"%s\" %s", downtime.getTablename(), tags, strings.TrimSpace("Downtime start: <br>"+downtime.comment), helper.CastStringTimeFromSToMs(downtime.entryTime)) end := fmt.Sprintf("%s%s message=\"%s\" %s", downtime.getTablename(), tags, strings.TrimSpace("Downtime end: <br>"+downtime.comment), helper.CastStringTimeFromSToMs(downtime.endTime)) return start + "\n" + end } logging.GetLogger().Criticalf("This influxversion [%f] given in the config is not supported", version) panic("") }