package matches // import nocternity.net/gomonop/cmd/matches import ( "fmt" "strconv" "strings" "nocternity.net/gomonop/pkg/perfdata" "nocternity.net/gomonop/pkg/status" ) // resultsInfo contains information about results being processed. type resultsInfo struct { nWarns, nCrits, nUnknowns uint } // updateResults updates the result counters based on the specified status. func (info *resultsInfo) updateFrom(itemStatus status.Status) { switch itemStatus { case status.StatusCritical: info.nCrits++ case status.StatusWarning: info.nWarns++ case status.StatusUnknown: info.nUnknowns++ case status.StatusOK: // do nothing } } // toProblems generate the list of problems found while running the plugin, // as a string which can be returned to the monitoring server. func (info *resultsInfo) toProblems() string { problems := []string{} if info.nCrits > 0 { problems = append(problems, fmt.Sprintf("%d value(s) critical", info.nCrits), ) } if info.nWarns > 0 { problems = append(problems, fmt.Sprintf("%d value(s) warning", info.nWarns), ) } if info.nUnknowns > 0 { problems = append(problems, fmt.Sprintf("%d value(s) unknown", info.nUnknowns), ) } if len(problems) == 0 { problems = append(problems, "No match errors") } return strings.Join(problems, ", ") } // toStatus computes the final status of the plugin based on the status // counters. func (info *resultsInfo) toStatus() status.Status { switch { case info.nCrits > 0: return status.StatusCritical case info.nWarns > 0: return status.StatusWarning case info.nUnknowns > 0: return status.StatusUnknown default: return status.StatusOK } } // checkCounters checks the match counters against their configured thresholds, // if any, and adds the corresponding perf data to the result. It initializes a // resultsInfo structure containing the counts of critical, warning and unknown // statuses gathered so far. func (pluginInst *matchesPlugin) checkCounters() resultsInfo { info := resultsInfo{} for index := range pluginInst.counters { config := &pluginInst.matches[index] var nature string if config.isRegexp { nature = "regexp" } else { nature = "substring" } label := fmt.Sprintf("#%2d : %s %s", index+1, nature, config.matchString) value := strconv.Itoa(pluginInst.counters[index]) pdat := perfdata.New(label, perfdata.UomNone, value) pdat.SetWarn(config.warn) pdat.SetCrit(config.crit) pluginInst.results.AddPerfData(pdat) info.updateFrom(pdat.GetStatus()) } return info } // checkUnmatched checks the unmatched lines counters, applying a limit if // strict mode is enabled. The corresponding performance data is added to the // result. func (pluginInst *matchesPlugin) checkUnmatched(info *resultsInfo) { umlPdat := perfdata.New("unmatched", perfdata.UomNone, strconv.Itoa(pluginInst.unmatchedLines)) if pluginInst.strict { umlPdat.SetCrit(perfdata.RangeMinMax("~", "0")) } info.updateFrom(umlPdat.GetStatus()) pluginInst.results.AddPerfData(umlPdat) } // checkResults checks the various counters against their configured thresholds, // and the strict mode failure count. func (pluginInst *matchesPlugin) checkResults(readError error) { info := pluginInst.checkCounters() pluginInst.checkUnmatched(&info) if readError != nil { pluginInst.results.AddLinef("Error while reading data: %s", readError.Error()) info.nUnknowns++ } pluginInst.results.SetState(info.toStatus(), info.toProblems()) }