diff --git a/collector/IPrintable.go b/collector/IPrintable.go index 5e8ddba..72575cc 100644 --- a/collector/IPrintable.go +++ b/collector/IPrintable.go @@ -2,7 +2,7 @@ package collector //Printable this interface should be used to push data into the queue. type Printable interface { - PrintForInfluxDB(version string) string + PrintForInfluxDB(version string, i int) string PrintForElasticsearch(version, index string) string TestTargetFilter(string) bool } diff --git a/collector/SimplePrintable.go b/collector/SimplePrintable.go index 2d60df5..ca7c89e 100644 --- a/collector/SimplePrintable.go +++ b/collector/SimplePrintable.go @@ -10,7 +10,7 @@ type SimplePrintable struct { } //PrintForInfluxDB generates an String for InfluxDB -func (p SimplePrintable) PrintForInfluxDB(version string) string { +func (p SimplePrintable) PrintForInfluxDB(version string, i int) string { if p.Datatype == data.InfluxDB { return p.Text } diff --git a/collector/livestatus/Collector.go b/collector/livestatus/Collector.go index f553a49..d78aa2d 100644 --- a/collector/livestatus/Collector.go +++ b/collector/livestatus/Collector.go @@ -248,7 +248,7 @@ Loop: for roundsToWait != 0 { select { case versionPrintable := <-printables: - version = versionPrintable.PrintForInfluxDB("0") + version = versionPrintable.PrintForInfluxDB("0", 0) break Loop case <-time.After(oneMinute): if i < roundsToWait { diff --git a/collector/livestatus/CommentData.go b/collector/livestatus/CommentData.go index 6d55a47..a816345 100644 --- a/collector/livestatus/CommentData.go +++ b/collector/livestatus/CommentData.go @@ -19,7 +19,7 @@ func (comment *CommentData) sanitizeValues() { } //PrintForInfluxDB prints the data in influxdb lineformat -func (comment CommentData) PrintForInfluxDB(version string) string { +func (comment CommentData) PrintForInfluxDB(version string, i int) string { comment.sanitizeValues() if helper.VersionOrdinal(version) >= helper.VersionOrdinal("0.9") { var tags string diff --git a/collector/livestatus/DowntimeData.go b/collector/livestatus/DowntimeData.go index 59ccaa8..4f39c24 100644 --- a/collector/livestatus/DowntimeData.go +++ b/collector/livestatus/DowntimeData.go @@ -21,7 +21,7 @@ func (downtime *DowntimeData) sanitizeValues() { } //PrintForInfluxDB prints the data in influxdb lineformat -func (downtime DowntimeData) PrintForInfluxDB(version string) string { +func (downtime DowntimeData) PrintForInfluxDB(version string, i int) string { downtime.sanitizeValues() if helper.VersionOrdinal(version) >= helper.VersionOrdinal("0.9") { tags := ",type=downtime,author=" + downtime.author diff --git a/collector/livestatus/NotificationData.go b/collector/livestatus/NotificationData.go index dbc814f..08e7eb8 100644 --- a/collector/livestatus/NotificationData.go +++ b/collector/livestatus/NotificationData.go @@ -23,7 +23,7 @@ func (notification *NotificationData) sanitizeValues() { } //PrintForInfluxDB prints the data in influxdb lineformat -func (notification NotificationData) PrintForInfluxDB(version string) string { +func (notification NotificationData) PrintForInfluxDB(version string, i int) string { notification.sanitizeValues() if helper.VersionOrdinal(version) >= helper.VersionOrdinal("0.9") { var tags string diff --git a/collector/nagflux/NagfluxPrintable.go b/collector/nagflux/NagfluxPrintable.go index fdab76d..27c8a35 100644 --- a/collector/nagflux/NagfluxPrintable.go +++ b/collector/nagflux/NagfluxPrintable.go @@ -16,7 +16,7 @@ type Printable struct { } //PrintForInfluxDB prints the data in influxdb lineformat -func (p Printable) PrintForInfluxDB(version string) string { +func (p Printable) PrintForInfluxDB(version string, i int) string { if helper.VersionOrdinal(version) >= helper.VersionOrdinal("0.9") { line := p.Table if len(p.tags) > 0 { diff --git a/collector/spoolfile/performanceData.go b/collector/spoolfile/performanceData.go index 6f3bb12..5935b7f 100644 --- a/collector/spoolfile/performanceData.go +++ b/collector/spoolfile/performanceData.go @@ -21,7 +21,7 @@ type PerformanceData struct { } //PrintForInfluxDB prints the data in influxdb lineformat -func (p PerformanceData) PrintForInfluxDB(version string) string { +func (p PerformanceData) PrintForInfluxDB(version string, i int) string { if helper.VersionOrdinal(version) >= helper.VersionOrdinal("0.9") { tableName := fmt.Sprintf(`metrics,host=%s`, helper.SanitizeInfluxInput(p.Hostname)) if p.Service == "" { @@ -29,10 +29,25 @@ func (p PerformanceData) PrintForInfluxDB(version string) string { } else { tableName += fmt.Sprintf(`,service=%s`, helper.SanitizeInfluxInput(p.Service)) } - tableName += fmt.Sprintf(`,command=%s,performanceLabel=%s`, + var fieldsString = "" + if config.GetConfig().InfluxDBGlobal.StorePerformanceLabelAsField { + tableName += fmt.Sprintf(`,performanceLabelIndex=%d`, + i, + ) + } + + tableName += fmt.Sprintf(`,command=%s`, helper.SanitizeInfluxInput(p.Command), - helper.SanitizeInfluxInput(p.PerformanceLabel), ) + if config.GetConfig().InfluxDBGlobal.StorePerformanceLabelAsField { + fieldsString += fmt.Sprintf(`,performanceLabel="%s"`, + helper.SanitizeInfluxField(p.PerformanceLabel), + ) + } else { + tableName += fmt.Sprintf(`,performanceLabel=%s`, + helper.SanitizeInfluxInput(p.PerformanceLabel), + ) + } if len(p.Tags) > 0 { tableName += fmt.Sprintf(`,%s`, helper.PrintMapAsString(helper.SanitizeMap(p.Tags), ",", "=")) } @@ -41,6 +56,7 @@ func (p PerformanceData) PrintForInfluxDB(version string) string { } tableName += fmt.Sprintf(` %s`, helper.PrintMapAsString(helper.SanitizeMap(p.Fields), ",", "=")) + tableName += fieldsString tableName += fmt.Sprintf(" %s\n", p.Time) return tableName } diff --git a/config.gcfg.example b/config.gcfg.example index 8ed00ff..b877d6d 100644 --- a/config.gcfg.example +++ b/config.gcfg.example @@ -54,6 +54,12 @@ NastyStringToReplace = "" HostcheckAlias = "hostcheck" ClientTimeout = 5 + # on big installations with lot of checks that have device dependend performance labels + # e.g. check_interface_table, the series cardinality in influxdb can explode and therefore + # cause write timeouts. + # In such cases, setting PerformanceLabel as Field value will significantly reduce the series + # cardinality. + StorePerformanceLabelAsField = false [InfluxDB "nagflux"] Enabled = true diff --git a/config/Config.go b/config/Config.go index 496304b..113da27 100644 --- a/config/Config.go +++ b/config/Config.go @@ -30,11 +30,12 @@ type Config struct { PrometheusAddress string } InfluxDBGlobal struct { - CreateDatabaseIfNotExists bool - NastyString string - NastyStringToReplace string - HostcheckAlias string - ClientTimeout int + CreateDatabaseIfNotExists bool + NastyString string + NastyStringToReplace string + HostcheckAlias string + ClientTimeout int + StorePerformanceLabelAsField bool } InfluxDB map[string]*struct { Enabled bool diff --git a/helper/influx.go b/helper/influx.go index a19596e..19042fe 100644 --- a/helper/influx.go +++ b/helper/influx.go @@ -28,6 +28,23 @@ func SanitizeInfluxInput(input string) string { return input } +//SanitizeInfluxField escapes '"' chars only +func SanitizeInfluxField(input string) string { + + if config.GetConfig().InfluxDBGlobal.NastyString != "" { + input = strings.Replace( + input, + config.GetConfig().InfluxDBGlobal.NastyString, + config.GetConfig().InfluxDBGlobal.NastyStringToReplace, + -1, + ) + } + + input = strings.Replace(input, "\"", `\"`, -1) + + return input +} + //SanitizeMap calls SanitizeInfluxInput in key and value func SanitizeMap(input map[string]string) map[string]string { result := map[string]string{} diff --git a/target/influx/Worker.go b/target/influx/Worker.go index 61a5de3..d87fd02 100644 --- a/target/influx/Worker.go +++ b/target/influx/Worker.go @@ -125,8 +125,8 @@ func (worker Worker) sendBuffer(queries []collector.Printable) { } var lineQueries []string - for _, query := range queries { - cast, castErr := worker.castJobToString(query) + for i, query := range queries { + cast, castErr := worker.castJobToString(query, i) if castErr == nil { lineQueries = append(lineQueries, cast) } @@ -192,7 +192,7 @@ func (worker Worker) readQueriesFromQueue() []string { select { case query = <-worker.jobs: if query.TestTargetFilter(worker.target.Name) { - cast, err := worker.castJobToString(query) + cast, err := worker.castJobToString(query, 0) if err == nil { queries = append(queries, cast) } @@ -305,12 +305,12 @@ func (worker Worker) dumpQueries(filename string, queries []string) { } //Converts an collector.Printable to a string. -func (worker Worker) castJobToString(job collector.Printable) (string, error) { +func (worker Worker) castJobToString(job collector.Printable, i int) (string, error) { var result string var err error if helper.VersionOrdinal(worker.version) >= helper.VersionOrdinal("0.9") { - result = job.PrintForInfluxDB(worker.version) + result = job.PrintForInfluxDB(worker.version, i) } else { worker.log.Fatalf("This influxversion [%s] given in the config is not supported", worker.version) err = errors.New("This influxversion given in the config is not supported")