diff --git a/.drone.yml b/.drone.yml index 61c2beeb..4fbaecfe 100644 --- a/.drone.yml +++ b/.drone.yml @@ -54,7 +54,7 @@ services: - 6381 - name: keydb-01 - image: "eqalpha/keydb:x86_64_v6.3.1" + image: "eqalpha/keydb:x86_64_v6.3.4" pull: if-not-exists commands: - "keydb-server --protected-mode no --port 6401 --dbfilename dump-keydb-01.rdb" @@ -62,7 +62,7 @@ services: - 6401 - name: keydb-02 - image: "eqalpha/keydb:x86_64_v6.3.1" + image: "eqalpha/keydb:x86_64_v6.3.4" pull: if-not-exists commands: - "keydb-server --protected-mode no --port 6402 --active-replica yes --replicaof keydb-01 6401 --dbfilename dump-keydb-02.rdb" @@ -70,12 +70,12 @@ services: - 6402 - name: redis-cluster - image: grokzen/redis-cluster:6.2.10 + image: grokzen/redis-cluster:6.2.11 pull: if-not-exists ports: [ 7000, 7001, 7002, 7003, 7004, 7005 ] - name: redis-cluster-password - image: bitnami/redis-cluster + image: bitnami/redis-cluster:latest environment: REDIS_PORT_NUMBER: 7006 REDIS_PASSWORD: redis-password diff --git a/README.md b/README.md index 488e1dde..0ab8c969 100644 --- a/README.md +++ b/README.md @@ -148,7 +148,7 @@ Prometheus uses file watches and all changes to the json file are applied immedi | check-single-keys | REDIS_EXPORTER_CHECK_SINGLE_KEYS | Comma separated list of keys to export value and length/size, eg: `db3=user_count` will export key `user_count` from db `3`. db defaults to `0` if omitted. The keys specified with this flag will be looked up directly without any glob pattern matching. Use this option if you don't need glob pattern matching; it is faster than `check-keys`. | | check-streams | REDIS_EXPORTER_CHECK_STREAMS | Comma separated list of stream-patterns to export info about streams, groups and consumers. Syntax is the same as `check-keys`. | | check-single-streams | REDIS_EXPORTER_CHECK_SINGLE_STREAMS | Comma separated list of streams to export info about streams, groups and consumers. The streams specified with this flag will be looked up directly without any glob pattern matching. Use this option if you don't need glob pattern matching; it is faster than `check-streams`. | -| streams-exclude-consumer-metrics | REDIS_EXPORTER_STREAMS_EXCLUDE_CONSUMER_METRICS | Don't collect per consumer metrics for streams (decreases amount of metrics and cardinality). | +| streams-exclude-consumer-metrics | REDIS_EXPORTER_STREAMS_EXCLUDE_CONSUMER_METRICS | Don't collect per consumer metrics for streams (decreases amount of metrics and cardinality). | | check-keys-batch-size | REDIS_EXPORTER_CHECK_KEYS_BATCH_SIZE | Approximate number of keys to process in each execution. This is basically the COUNT option that will be passed into the SCAN command as part of the execution of the key or key group metrics, see [COUNT option](https://redis.io/commands/scan#the-count-option). Larger value speeds up scanning. Still Redis is a single-threaded app, huge `COUNT` can affect production environment. | | count-keys | REDIS_EXPORTER_COUNT_KEYS | Comma separated list of patterns to count, eg: `db3=sessions:*` will count all keys with prefix `sessions:` from db `3`. db defaults to `0` if omitted. Warning: The exporter runs SCAN to count the keys. This might not perform well on large databases. | | script | REDIS_EXPORTER_SCRIPT | Comma separated list of path(s) to Redis Lua script(s) for gathering extra metrics. | @@ -161,7 +161,7 @@ Prometheus uses file watches and all changes to the json file are applied immedi | redis-only-metrics | REDIS_EXPORTER_REDIS_ONLY_METRICS | Whether to also export go runtime metrics, defaults to false. | | include-config-metrics | REDIS_EXPORTER_INCL_CONFIG_METRICS | Whether to include all config settings as metrics, defaults to false. | | include-system-metrics | REDIS_EXPORTER_INCL_SYSTEM_METRICS | Whether to include system metrics like `total_system_memory_bytes`, defaults to false. | -| exclude-latency-histogram-metrics | REDIS_EXPORTER_EXCLUDE_LATENCY_HISTOGRAM_METRICS | Do not try to collect latency histogram metrics (to avoid `WARNING, LOGGED ONCE ONLY: cmd LATENCY HISTOGRAM` error on Redis < v7). | +| exclude-latency-histogram-metrics | REDIS_EXPORTER_EXCLUDE_LATENCY_HISTOGRAM_METRICS | Do not try to collect latency histogram metrics (to avoid `WARNING, LOGGED ONCE ONLY: cmd LATENCY HISTOGRAM` error on Redis < v7). | | redact-config-metrics | REDIS_EXPORTER_REDACT_CONFIG_METRICS | Whether to redact config settings that include potentially sensitive information like passwords. | | ping-on-connect | REDIS_EXPORTER_PING_ON_CONNECT | Whether to ping the redis instance after connecting and record the duration as a metric, defaults to false. | | is-tile38 | REDIS_EXPORTER_IS_TILE38 | Whether to scrape Tile38 specific metrics, defaults to false. | @@ -179,7 +179,7 @@ Prometheus uses file watches and all changes to the json file are applied immedi | set-client-name | REDIS_EXPORTER_SET_CLIENT_NAME | Whether to set client name to redis_exporter, defaults to true. | | check-key-groups | REDIS_EXPORTER_CHECK_KEY_GROUPS | Comma separated list of [LUA regexes](https://www.lua.org/pil/20.1.html) for classifying keys into groups. The regexes are applied in specified order to individual keys, and the group name is generated by concatenating all capture groups of the first regex that matches a key. A key will be tracked under the `unclassified` group if none of the specified regexes matches it. | | max-distinct-key-groups | REDIS_EXPORTER_MAX_DISTINCT_KEY_GROUPS | Maximum number of distinct key groups that can be tracked independently *per Redis database*. If exceeded, only key groups with the highest memory consumption within the limit will be tracked separately, all remaining key groups will be tracked under a single `overflow` key group. | -| config-command | REDIS_EXPORTER_CONFIG_COMMAND | What to use for the CONFIG command, defaults to `CONFIG`. | +| config-command | REDIS_EXPORTER_CONFIG_COMMAND | What to use for the CONFIG command, defaults to `CONFIG`, , set to "-" to skip config metrics extraction. | Redis instance addresses can be tcp addresses: `redis://localhost:6379`, `redis.example.com:6379` or e.g. unix sockets: `unix:///tmp/redis.sock`.\ SSL is supported by using the `rediss://` schema, for example: `rediss://azure-ssl-enabled-host.redis.cache.windows.net:6380` (note that the port is required when connecting to a non-standard 6379 port, e.g. with Azure Redis instances).\ diff --git a/exporter/exporter.go b/exporter/exporter.go index 7d30b413..e7160872 100644 --- a/exporter/exporter.go +++ b/exporter/exporter.go @@ -594,14 +594,18 @@ func (e *Exporter) scrapeRedisHost(ch chan<- prometheus.Metric) error { } dbCount := 0 - if config, err := redis.Values(doRedisCmd(c, e.options.ConfigCommandName, "GET", "*")); err == nil { - dbCount, err = e.extractConfigMetrics(ch, config) - if err != nil { - log.Errorf("Redis CONFIG err: %s", err) - return err - } + if e.options.ConfigCommandName == "-" { + log.Debugf("Skipping extractConfigMetrics()") } else { - log.Debugf("Redis CONFIG err: %s", err) + if config, err := redis.Values(doRedisCmd(c, e.options.ConfigCommandName, "GET", "*")); err == nil { + dbCount, err = e.extractConfigMetrics(ch, config) + if err != nil { + log.Errorf("Redis extractConfigMetrics() err: %s", err) + return err + } + } else { + log.Debugf("Redis CONFIG err: %s", err) + } } infoAll, err := redis.String(doRedisCmd(c, "INFO", "ALL")) diff --git a/exporter/exporter_test.go b/exporter/exporter_test.go index 26d18610..6d8c270e 100644 --- a/exporter/exporter_test.go +++ b/exporter/exporter_test.go @@ -244,6 +244,28 @@ func TestIncludeConfigMetrics(t *testing.T) { } } +func TestExcludeConfigMetricsViaCONFIGCommand(t *testing.T) { + for _, inc := range []bool{false, true} { + r := prometheus.NewRegistry() + ts := httptest.NewServer(promhttp.HandlerFor(r, promhttp.HandlerOpts{})) + e, _ := NewRedisExporter(os.Getenv("TEST_REDIS_URI"), + Options{ + Namespace: "test", + ConfigCommandName: "-", + InclConfigMetrics: inc}) + r.Register(e) + + what := `test_config_key_value{key="appendonly",value="no"}` + + body := downloadURL(t, ts.URL+"/metrics") + if strings.Contains(body, what) { + t.Fatalf("found test_config_key_value but should have skipped CONFIG call") + } + + ts.Close() + } +} + func TestNonExistingHost(t *testing.T) { e, _ := NewRedisExporter("unix:///tmp/doesnt.exist", Options{Namespace: "test"}) diff --git a/main.go b/main.go index 3102f55d..90215d56 100644 --- a/main.go +++ b/main.go @@ -74,7 +74,7 @@ func main() { listenAddress = flag.String("web.listen-address", getEnv("REDIS_EXPORTER_WEB_LISTEN_ADDRESS", ":9121"), "Address to listen on for web interface and telemetry.") metricPath = flag.String("web.telemetry-path", getEnv("REDIS_EXPORTER_WEB_TELEMETRY_PATH", "/metrics"), "Path under which to expose metrics.") logFormat = flag.String("log-format", getEnv("REDIS_EXPORTER_LOG_FORMAT", "txt"), "Log format, valid options are txt and json") - configCommand = flag.String("config-command", getEnv("REDIS_EXPORTER_CONFIG_COMMAND", "CONFIG"), "What to use for the CONFIG command") + configCommand = flag.String("config-command", getEnv("REDIS_EXPORTER_CONFIG_COMMAND", "CONFIG"), "What to use for the CONFIG command, set to \"-\" to skip config metrics extraction") connectionTimeout = flag.String("connection-timeout", getEnv("REDIS_EXPORTER_CONNECTION_TIMEOUT", "15s"), "Timeout for connection to Redis instance") tlsClientKeyFile = flag.String("tls-client-key-file", getEnv("REDIS_EXPORTER_TLS_CLIENT_KEY_FILE", ""), "Name of the client key file (including full path) if the server requires TLS client authentication") tlsClientCertFile = flag.String("tls-client-cert-file", getEnv("REDIS_EXPORTER_TLS_CLIENT_CERT_FILE", ""), "Name of the client certificate file (including full path) if the server requires TLS client authentication")