diff --git a/tools/pika_exporter/exporter/metrics/parser.go b/tools/pika_exporter/exporter/metrics/parser.go index 739ee9b6d2..a66bd6f54f 100644 --- a/tools/pika_exporter/exporter/metrics/parser.go +++ b/tools/pika_exporter/exporter/metrics/parser.go @@ -17,10 +17,141 @@ const ( ) type ParseOption struct { - Version *semver.Version - Extracts map[string]string - ExtractsProxy map[string][]int64 - Info string + Version *semver.Version + Extracts map[string]string + ExtractsProxy map[string][]int64 + Info string + CurrentVersion VersionChecker +} +type VersionChecker interface { + CheckContainsEmptyValueName(key string) bool + CheckContainsEmptyRegexName(key string) bool + InitVersionChecker() +} +type VersionChecker336 struct { + EmptyValueName []string + EmptyRegexName []string +} + +func (v *VersionChecker336) InitVersionChecker() { + if v.EmptyValueName == nil { + v.EmptyValueName = []string{ + "instantaneous_output_repl_kbps", + "total_net_output_bytes", + "cache_db_num", + "hits_per_sec", + "cache_status", + "total_net_input_bytes", + "instantaneous_output_kbps", + "instantaneous_input_kbps", + "total_net_repl_input_bytes", + "instantaneous_input_repl_kbps", + "slow_logs_count", + "total_net_repl_output_bytes", + "cache_memory", + } + } + if v.EmptyRegexName == nil { + v.EmptyRegexName = []string{ + "hitratio_per_sec", + } + } +} +func (v *VersionChecker336) CheckContainsEmptyValueName(key string) bool { + for _, str := range v.EmptyValueName { + if str == key { + return true + } + } + return false +} +func (v *VersionChecker336) CheckContainsEmptyRegexName(key string) bool { + for _, str := range v.EmptyRegexName { + if str == key { + return true + } + } + return false +} + +type VersionChecker350 struct { + EmptyValueName []string + EmptyRegexName []string +} + +func (v *VersionChecker350) InitVersionChecker() { + if v.EmptyValueName == nil { + v.EmptyValueName = []string{ + "cache_db_num", + "cache_status", + "cache_memory", + "hits_per_sec", + "slow_logs_count", + } + } + if v.EmptyRegexName == nil { + v.EmptyRegexName = []string{ + "hitratio_per_sec", + } + } +} +func (v *VersionChecker350) CheckContainsEmptyValueName(key string) bool { + for _, str := range v.EmptyValueName { + if str == key { + return true + } + } + return false +} +func (v *VersionChecker350) CheckContainsEmptyRegexName(key string) bool { + for _, str := range v.EmptyRegexName { + if str == key { + return true + } + } + return false +} + +type VersionChecker355 struct { + EmptyValueName []string + EmptyRegexName []string +} + +func (v *VersionChecker355) InitVersionChecker() { + if v.EmptyValueName == nil { + v.EmptyValueName = []string{ + "cache_db_num", + "cache_status", + "cache_memory", + "hits_per_sec", + } + } + if v.EmptyRegexName == nil { + v.EmptyRegexName = []string{ + "hitratio_per_sec", + "keyspace_info_>=3.1.0", + "keyspace_info_all_>=3.3.3", + "binlog_>=3.2.0", + "keyspace_last_start_time", + "is_scaning_keyspace", + } + } +} +func (v *VersionChecker355) CheckContainsEmptyValueName(key string) bool { + for _, str := range v.EmptyValueName { + if str == key { + return true + } + } + return false +} +func (v *VersionChecker355) CheckContainsEmptyRegexName(key string) bool { + for _, str := range v.EmptyRegexName { + if str == key { + return true + } + } + return false } type Parser interface { @@ -112,9 +243,10 @@ func (p *regexParser) Parse(m MetricMeta, c Collector, opt ParseOption) { matchMaps := p.regMatchesToMap(s) if len(matchMaps) == 0 { - log.Warnf("regexParser::Parse reg find sub match nil. name:%s", p.name) + if opt.CurrentVersion == nil || !opt.CurrentVersion.CheckContainsEmptyRegexName(p.name) { + log.Warnf("regexParser::Parse reg find sub match nil. name:%s", p.name) + } } - extracts := make(map[string]string) for k, v := range opt.Extracts { extracts[k] = v @@ -136,7 +268,6 @@ func (p *regexParser) regMatchesToMap(s string) []map[string]string { multiMatches := p.reg.FindAllStringSubmatch(s, -1) if len(multiMatches) == 0 { - log.Errorf("regexParser::regMatchesToMap reg find sub match nil. name:%s", p.name) return nil } @@ -172,8 +303,11 @@ func (p *normalParser) Parse(m MetricMeta, c Collector, opt ParseOption) { if m.ValueName != "" { if v, ok := findInMap(m.ValueName, opt.Extracts); !ok { - log.Warnf("normalParser::Parse not found value. metricName:%s valueName:%s", m.Name, m.ValueName) + if opt.CurrentVersion == nil || !opt.CurrentVersion.CheckContainsEmptyValueName(m.ValueName) { + log.Warnf("normalParser::Parse not found value. metricName:%s valueName:%s", m.Name, m.ValueName) + } return + } else { metric.Value = convertToFloat64(v) } @@ -208,7 +342,6 @@ func (p *timeParser) Parse(m MetricMeta, c Collector, opt ParseOption) { if m.ValueName != "" { if v, ok := findInMap(m.ValueName, opt.Extracts); !ok { - log.Warnf("timeParser::Parse not found value. metricName:%s valueName:%s", m.Name, m.ValueName) return } else { t, err := convertTimeToUnix(v) @@ -227,6 +360,7 @@ func (p *timeParser) Parse(m MetricMeta, c Collector, opt ParseOption) { } func findInMap(key string, ms ...map[string]string) (string, bool) { + for _, m := range ms { if v, ok := m[key]; ok { return v, true @@ -234,7 +368,6 @@ func findInMap(key string, ms ...map[string]string) (string, bool) { } return "", false } - func trimSpace(s string) string { return strings.TrimRight(strings.TrimLeft(s, " "), " ") } diff --git a/tools/pika_exporter/exporter/pika.go b/tools/pika_exporter/exporter/pika.go index 2e5c27e2dd..e3fe2631c9 100644 --- a/tools/pika_exporter/exporter/pika.go +++ b/tools/pika_exporter/exporter/pika.go @@ -252,9 +252,10 @@ func (e *exporter) collectInfo(c *client, ch chan<- prometheus.Metric) error { return nil }) parseOpt := metrics.ParseOption{ - Version: version, - Extracts: extracts, - Info: info, + Version: version, + Extracts: extracts, + Info: info, + CurrentVersion: selectversion(version.Original()), } for _, m := range metrics.MetricConfigs { m.Parse(m, collector, parseOpt) @@ -263,6 +264,37 @@ func (e *exporter) collectInfo(c *client, ch chan<- prometheus.Metric) error { return nil } +const ( + VERSION_336 = "3.3.6" + VERSION_350 = "3.5.0" + VERSION_355 = "3.5.5" +) + +func selectversion(version string) metrics.VersionChecker { + if !isValidVersion(version) { + log.Warnf("Invalid version format: %s", version) + return nil + } + var v metrics.VersionChecker + switch version { + case VERSION_336: + v = &metrics.VersionChecker336{} + case VERSION_355: + v = &metrics.VersionChecker355{} + case VERSION_350: + v = &metrics.VersionChecker350{} + default: + return nil + } + v.InitVersionChecker() + return v +} + +// isValidVersion validates the version string format (e.g., x.y.z) +func isValidVersion(version string) bool { + matched, _ := regexp.MatchString(`^\d+\.\d+\.\d+$`, version) + return matched +} func (e *exporter) collectKeys(c *client) error { allKeys := append([]dbKeyPair{}, e.keys...) keys, err := getKeysFromPatterns(c, e.keyPatterns, e.scanCount)