@@ -2,6 +2,7 @@ package exporter
22
33import (
44 "fmt"
5+ "log/slog"
56 "net/http"
67 "net/url"
78 "runtime"
@@ -16,7 +17,6 @@ import (
1617 "github.com/gomodule/redigo/redis"
1718 "github.com/prometheus/client_golang/prometheus"
1819 "github.com/prometheus/client_golang/prometheus/promhttp"
19- log "github.com/sirupsen/logrus"
2020)
2121
2222type BuildInfo struct {
@@ -93,7 +93,7 @@ type Options struct {
9393
9494// NewRedisExporter returns a new exporter of Redis metrics.
9595func NewRedisExporter (uri string , opts Options ) (* Exporter , error ) {
96- log . Debugf ("NewRedisExporter options: %#v " , opts )
96+ slog . Debug ("NewRedisExporter options" , "options " , opts )
9797
9898 switch {
9999 case strings .HasPrefix (uri , "valkey://" ):
@@ -102,7 +102,7 @@ func NewRedisExporter(uri string, opts Options) (*Exporter, error) {
102102 uri = strings .Replace (uri , "valkeys://" , "rediss://" , 1 )
103103 }
104104
105- log . Debugf ( "NewRedisExporter = using redis uri: %s " , uri )
105+ slog . Debug ( "Using redis URI" , "uri " , uri )
106106
107107 if opts .Registry == nil {
108108 opts .Registry = prometheus .NewRegistry ()
@@ -407,31 +407,31 @@ func NewRedisExporter(uri string, opts Options) (*Exporter, error) {
407407 if keys , err := parseKeyArg (opts .CheckKeys ); err != nil {
408408 return nil , fmt .Errorf ("couldn't parse check-keys: %s" , err )
409409 } else {
410- log . Debugf ("keys: %#v " , keys )
410+ slog . Debug ("keys" , "keys " , keys )
411411 }
412412
413413 if singleKeys , err := parseKeyArg (opts .CheckSingleKeys ); err != nil {
414414 return nil , fmt .Errorf ("couldn't parse check-single-keys: %s" , err )
415415 } else {
416- log . Debugf ("singleKeys: %#v " , singleKeys )
416+ slog . Debug ("singleKeys" , "singleKeys " , singleKeys )
417417 }
418418
419419 if streams , err := parseKeyArg (opts .CheckStreams ); err != nil {
420420 return nil , fmt .Errorf ("couldn't parse check-streams: %s" , err )
421421 } else {
422- log . Debugf ("streams: %#v " , streams )
422+ slog . Debug ("streams" , "streams " , streams )
423423 }
424424
425425 if singleStreams , err := parseKeyArg (opts .CheckSingleStreams ); err != nil {
426426 return nil , fmt .Errorf ("couldn't parse check-single-streams: %s" , err )
427427 } else {
428- log . Debugf ("singleStreams: %#v " , singleStreams )
428+ slog . Debug ("singleStreams" , "singleStreams " , singleStreams )
429429 }
430430
431431 if countKeys , err := parseKeyArg (opts .CountKeys ); err != nil {
432432 return nil , fmt .Errorf ("couldn't parse count-keys: %s" , err )
433433 } else {
434- log . Debugf ("countKeys: %#v " , countKeys )
434+ slog . Debug ("countKeys" , "countKeys " , countKeys )
435435 }
436436
437437 if opts .InclSystemMetrics {
@@ -571,6 +571,21 @@ func (e *Exporter) Describe(ch chan<- *prometheus.Desc) {
571571 ch <- e .targetScrapeRequestErrors .Desc ()
572572}
573573
574+ func ParseLogLevel (level string ) (slog.Level , error ) {
575+ switch strings .ToUpper (level ) {
576+ case "DEBUG" :
577+ return slog .LevelDebug , nil
578+ case "INFO" :
579+ return slog .LevelInfo , nil
580+ case "WARN" , "WARNING" :
581+ return slog .LevelWarn , nil
582+ case "ERROR" :
583+ return slog .LevelError , nil
584+ default :
585+ return slog .LevelInfo , fmt .Errorf ("invalid log level: %s" , level )
586+ }
587+ }
588+
574589// Collect fetches new metrics from the RedisHost and updates the appropriate metrics.
575590func (e * Exporter ) Collect (ch chan <- prometheus.Metric ) {
576591 e .Lock ()
@@ -607,13 +622,13 @@ func (e *Exporter) extractConfigMetrics(ch chan<- prometheus.Metric, config []in
607622 for pos := 0 ; pos < len (config )/ 2 ; pos ++ {
608623 strKey , err := redis .String (config [pos * 2 ], nil )
609624 if err != nil {
610- log . Errorf ("invalid config key name, err: %s, skipped " , err )
625+ slog . Error ("invalid config key name, skipped" , "error " , err )
611626 continue
612627 }
613628
614629 strVal , err := redis .String (config [pos * 2 + 1 ], nil )
615630 if err != nil {
616- log . Debugf ("invalid config value for key name %s, err: %s, skipped" , strKey , err )
631+ slog . Debug ("invalid config value for key name, skipped" , "key" , strKey , "error" , err )
617632 continue
618633 }
619634
@@ -678,7 +693,7 @@ func (e *Exporter) getKeyOperationConnection(defaultConn redis.Conn) (redis.Conn
678693}
679694
680695func (e * Exporter ) scrapeRedisHost (ch chan <- prometheus.Metric ) error {
681- defer log . Debugf ( "scrapeRedisHost() done" )
696+ defer slog . Debug ( "Finished scraping Redis host" , "address" , e . redisAddr )
682697
683698 startTime := time .Now ()
684699 c , err := e .connectToRedis ()
@@ -688,72 +703,72 @@ func (e *Exporter) scrapeRedisHost(ch chan<- prometheus.Metric) error {
688703 if err != nil {
689704 var redactedAddr string
690705 if redisURL , err2 := url .Parse (e .redisAddr ); err2 != nil {
691- log . Debugf ( "url.Parse( %s ) err: %s" , e .redisAddr , err2 )
706+ slog . Debug ( "Failed to parse URL" , "address" , e .redisAddr , "error" , err2 )
692707 redactedAddr = "<redacted>"
693708 } else {
694709 redactedAddr = redisURL .Redacted ()
695710 }
696- log . Errorf ("Couldn't connect to redis instance (%s) " , redactedAddr )
697- log . Debugf ( "connectToRedis( %s ) err: %s" , e .redisAddr , err )
711+ slog . Error ("Couldn't connect to redis instance" , "address " , redactedAddr )
712+ slog . Debug ( "Connect to redis failed" , "address" , e .redisAddr , "error" , err )
698713 return err
699714 }
700715 defer c .Close ()
701716
702- log . Debugf ( "connected to: %s " , e .redisAddr )
703- log . Debugf ("connecting took %f seconds" , connectTookSeconds )
717+ slog . Debug ( "Connected to redis" , "address " , e .redisAddr )
718+ slog . Debug ("connecting took seconds" , " seconds" , connectTookSeconds )
704719
705720 if e .options .PingOnConnect {
706721 startTime := time .Now ()
707722
708723 if _ , err := doRedisCmd (c , "PING" ); err != nil {
709- log . Errorf ("Couldn't PING server, err: %s " , err )
724+ slog . Error ("Couldn't PING server" , "error " , err )
710725 } else {
711726 pingTookSeconds := time .Since (startTime ).Seconds ()
712727 e .registerConstMetricGauge (ch , "exporter_last_scrape_ping_time_seconds" , pingTookSeconds )
713- log . Debugf ("PING took %f seconds" , pingTookSeconds )
728+ slog . Debug ("PING took seconds" , " seconds" , pingTookSeconds )
714729 }
715730 }
716731
717732 if e .options .SetClientName {
718733 if _ , err := doRedisCmd (c , "CLIENT" , "SETNAME" , "redis_exporter" ); err != nil {
719- log . Errorf ("Couldn't set client name, err: %s " , err )
734+ slog . Error ("Couldn't set client name" , "error " , err )
720735 }
721736 }
722737
723738 dbCount := 0
724739 if e .options .ConfigCommandName == "-" {
725- log . Debugf ("Skipping extractConfigMetrics() " )
740+ slog . Debug ("Skipping config metrics extraction " )
726741 } else {
727742 if config , err := redis .Values (doRedisCmd (c , e .options .ConfigCommandName , "GET" , "*" )); err == nil {
728743 dbCount , err = e .extractConfigMetrics (ch , config )
729744 if err != nil {
730- log . Errorf ( "Redis extractConfigMetrics() err: %s " , err )
745+ slog . Error ( "Failed to extract config metrics" , "error " , err )
731746 return err
732747 }
733748 } else {
734- log . Debugf ("Redis CONFIG err: %s " , err )
749+ slog . Debug ("Redis CONFIG err" , "error " , err )
735750 }
736751 }
737752
738753 infoAll , err := redis .String (doRedisCmd (c , "INFO" , "ALL" ))
739754 if err != nil || infoAll == "" {
740- log . Debugf ("Redis INFO ALL err: %s " , err )
755+ slog . Debug ("Redis INFO ALL err" , "error " , err )
741756 infoAll , err = redis .String (doRedisCmd (c , "INFO" ))
742757 if err != nil {
743- log . Errorf ("Redis INFO err: %s " , err )
758+ slog . Error ("Redis INFO err" , "error " , err )
744759 return err
745760 }
746761 }
747- log . Debugf ("Redis INFO ALL result: [%#v] " , infoAll )
762+ slog . Debug ("Redis INFO ALL result" , "result " , infoAll )
748763
749764 if strings .Contains (infoAll , "cluster_enabled:1" ) {
750765 if clusterInfo , err := redis .String (doRedisCmd (c , "CLUSTER" , "INFO" )); err == nil {
751766 e .extractClusterInfoMetrics (ch , clusterInfo )
752767
753- // in cluster mode Redis only supports one database, so no extra DB number padding needed
768+ // in cluster mode, Redis only supports one database, so no extra DB number padding needed
754769 dbCount = 1
755770 } else {
756- log . Errorf ("Redis CLUSTER INFO err: %s " , err )
771+ slog . Error ("Redis CLUSTER INFO err" , "error " , err )
757772 }
758773 } else if dbCount == 0 {
759774 // in non-cluster mode, if dbCount is zero, then "CONFIG" failed to retrieve a valid
@@ -762,7 +777,7 @@ func (e *Exporter) scrapeRedisHost(ch chan<- prometheus.Metric) error {
762777 dbCount = 16
763778 }
764779
765- log . Debugf ("dbCount: %d " , dbCount )
780+ slog . Debug ("dbCount" , "count " , dbCount )
766781
767782 role := e .extractInfoMetrics (ch , infoAll , dbCount )
768783
@@ -772,12 +787,13 @@ func (e *Exporter) scrapeRedisHost(ch chan<- prometheus.Metric) error {
772787
773788 // skip these metrics for master if SkipCheckKeysForRoleMaster is set
774789 // (can help with reducing workload on the master node)
775- log .Debugf ("checkKeys metric collection for role: %s SkipCheckKeysForRoleMaster flag: %#v" , role , e .options .SkipCheckKeysForRoleMaster )
790+ slog .Debug ("checkKeys metric collection for role" , "role" , role , "SkipCheckKeysForRoleMaster" , e .options .SkipCheckKeysForRoleMaster )
791+
776792 if role == InstanceRoleSlave || ! e .options .SkipCheckKeysForRoleMaster {
777793 // For key-based operations, use cluster connection if in cluster mode
778794 keyConn , err := e .getKeyOperationConnection (c )
779795 if err != nil {
780- log . Errorf ("failed to get key operation connection: %s " , err )
796+ slog . Error ("failed to get key operation connection" , "error " , err )
781797 } else {
782798 defer func () {
783799 if keyConn != c {
@@ -786,23 +802,22 @@ func (e *Exporter) scrapeRedisHost(ch chan<- prometheus.Metric) error {
786802 }()
787803
788804 if err := e .extractCheckKeyMetrics (ch , keyConn ); err != nil {
789- log . Errorf ("extractCheckKeyMetrics() err: %s " , err )
805+ slog . Error ("extractCheckKeyMetrics()" , "error " , err )
790806 }
791807
792808 e .extractCountKeysMetrics (ch , keyConn )
793809
794810 e .extractStreamMetrics (ch , keyConn )
795811 }
796812 } else {
797- log . Infof ("skipping checkKeys metrics, role: %s flag: %#v " , role , e .options .SkipCheckKeysForRoleMaster )
813+ slog . Info ("skipping checkKeys metrics" , " role" , role , "flag" , e .options .SkipCheckKeysForRoleMaster )
798814 }
799-
800815 e .extractSlowLogMetrics (ch , c )
801816
802817 // Key groups also need cluster connection for key operations
803818 keyGroupConn , err := e .getKeyOperationConnection (c )
804819 if err != nil {
805- log . Errorf ("failed to get key operation connection for key groups: %s " , err )
820+ slog . Error ("failed to get key operation connection for key groups" , "error " , err )
806821 } else {
807822 defer func () {
808823 if keyGroupConn != c {
0 commit comments