-
Notifications
You must be signed in to change notification settings - Fork 938
feat: add support for RDB current file size metric #1095
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
a4cdc84
11d06b1
e6d7516
f9061f8
ca4dc78
6a22782
5b57f63
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -76,6 +76,7 @@ type Options struct { | |
| ExcludeLatencyHistogramMetrics bool | ||
| RedactConfigMetrics bool | ||
| InclSystemMetrics bool | ||
| InclRdbFileSizeMetric bool | ||
| SkipTLSVerification bool | ||
| SetClientName bool | ||
| IsTile38 bool | ||
|
|
@@ -542,6 +543,7 @@ func NewRedisExporter(uri string, opts Options) (*Exporter, error) { | |
| "master_sync_in_progress": {txt: "Master sync in progress", lbls: []string{"master_host", "master_port"}}, | ||
| "module_info": {txt: "Information about loaded Redis module", lbls: []string{"name", "ver", "api", "filters", "usedby", "using"}}, | ||
| "number_of_distinct_key_groups": {txt: `Number of distinct key groups`, lbls: []string{"db"}}, | ||
| "rdb_current_size_bytes": {txt: "Current RDB file size in bytes"}, | ||
| "script_result": {txt: "Result of the collect script evaluation", lbls: []string{"filename"}}, | ||
| "script_values": {txt: "Values returned by the collect script", lbls: []string{"key", "filename"}}, | ||
| "search_index_num_docs": {txt: "Number of documents in search index", lbls: []string{"index_name"}}, | ||
|
|
@@ -824,10 +826,12 @@ func (e *Exporter) scrapeRedisHost(ch chan<- prometheus.Metric) error { | |
| } | ||
|
|
||
| dbCount := 0 | ||
| var config []interface{} | ||
| if e.options.ConfigCommandName == "-" { | ||
| log.Debugf("Skipping extractConfigMetrics()") | ||
| } else { | ||
| if config, err := redis.Values(doRedisCmd(c, e.options.ConfigCommandName, "GET", "*")); err == nil { | ||
| if cfg, err := redis.Values(doRedisCmd(c, e.options.ConfigCommandName, "GET", "*")); err == nil { | ||
| config = cfg | ||
| dbCount, err = e.extractConfigMetrics(ch, config) | ||
| if err != nil { | ||
| log.Errorf("Redis extractConfigMetrics() err: %s", err) | ||
|
|
@@ -936,5 +940,9 @@ func (e *Exporter) scrapeRedisHost(ch chan<- prometheus.Metric) error { | |
| } | ||
| } | ||
|
|
||
| if e.options.ConfigCommandName != "-" && e.options.InclRdbFileSizeMetric && len(config) > 0 { | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove the extra |
||
| e.extractRdbFileSizeMetric(ch, config) | ||
| } | ||
|
|
||
| return nil | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,83 @@ | ||
| package exporter | ||
|
|
||
| import ( | ||
| "os" | ||
| "path/filepath" | ||
| "strings" | ||
|
|
||
| "github.com/gomodule/redigo/redis" | ||
| "github.com/prometheus/client_golang/prometheus" | ||
| log "github.com/sirupsen/logrus" | ||
| ) | ||
|
|
||
| func (e *Exporter) extractRdbFileSizeMetric(ch chan<- prometheus.Metric, config []interface{}) { | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just simplified the config extraction anfd it's using a ma[string]string now which should make this code a lot simpler for instance,m you don't need to iterate over the config map any longer but can simply look up filename and directory. Please rebase and then use the config map. |
||
| if len(config) == 0 { | ||
| log.Debugf("Config is empty, cannot extract RDB file size") | ||
| return | ||
| } | ||
|
|
||
| // Validate config has even number of elements (key-value pairs) | ||
| if len(config)%2 != 0 { | ||
| log.Warnf("Invalid config format: odd number of elements (%d)", len(config)) | ||
| return | ||
| } | ||
|
|
||
| // Parse config to find dir and dbfilename | ||
| configMap := make(map[string]string) | ||
| for i := 0; i < len(config); i += 2 { | ||
| key, err := redis.String(config[i], nil) | ||
| if err != nil { | ||
| log.Warnf("Failed to parse config key at index %d: %s", i, err) | ||
| continue | ||
| } | ||
| value, err := redis.String(config[i+1], nil) | ||
| if err != nil { | ||
| log.Warnf("Failed to parse config value for key '%s': %s", key, err) | ||
| continue | ||
| } | ||
| configMap[key] = value | ||
| } | ||
|
|
||
| dir, dirOk := configMap["dir"] | ||
| dbfilename, dbfilenameOk := configMap["dbfilename"] | ||
|
|
||
| if !dirOk || !dbfilenameOk { | ||
| log.Warnf("Failed to find 'dir' or 'dbfilename' in config") | ||
| return | ||
| } | ||
|
|
||
| // Basic path validation to prevent directory traversal | ||
| if strings.Contains(dbfilename, "..") { | ||
| log.Warnf("Invalid dbfilename contains '..': %s", dbfilename) | ||
| return | ||
| } | ||
|
|
||
| rdbPath := filepath.Join(dir, dbfilename) | ||
| log.Debugf("RDB file path: %s", rdbPath) | ||
|
|
||
| fileInfo, err := os.Stat(rdbPath) | ||
| if err != nil { | ||
| if os.IsNotExist(err) { | ||
| log.Debugf("RDB file does not exist: %s", rdbPath) | ||
| // File doesn't exist, report 0 | ||
akshaykumar-vijapur marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| e.registerConstMetricGauge(ch, "rdb_current_size_bytes", 0) | ||
| return | ||
| } | ||
| if os.IsPermission(err) { | ||
| log.Warnf("Permission denied accessing RDB file: %s", rdbPath) | ||
| return | ||
| } | ||
| log.Warnf("Failed to stat RDB file %s: %s", rdbPath, err) | ||
| return | ||
| } | ||
|
|
||
| // Verify it's a regular file | ||
| if !fileInfo.Mode().IsRegular() { | ||
| log.Warnf("RDB path is not a regular file: %s (mode: %s)", rdbPath, fileInfo.Mode()) | ||
| return | ||
| } | ||
|
|
||
| fileSize := float64(fileInfo.Size()) | ||
akshaykumar-vijapur marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| log.Debugf("RDB file size: %d bytes", fileInfo.Size()) | ||
| e.registerConstMetricGauge(ch, "rdb_current_size_bytes", fileSize) | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instead of the extra variable, call
extractRdbFileSizeMetric()right up here, after line 839