Fix Redis output field type inconsistencies (#8678)
This commit is contained in:
parent
fbd54e84a2
commit
76c2201bbe
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
@ -46,6 +47,117 @@ type RedisClient struct {
|
||||||
tags map[string]string
|
tags map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RedisFieldTypes defines the types expected for each of the fields redis reports on
|
||||||
|
type RedisFieldTypes struct {
|
||||||
|
ActiveDefragHits int64 `json:"active_defrag_hits"`
|
||||||
|
ActiveDefragKeyHits int64 `json:"active_defrag_key_hits"`
|
||||||
|
ActiveDefragKeyMisses int64 `json:"active_defrag_key_misses"`
|
||||||
|
ActiveDefragMisses int64 `json:"active_defrag_misses"`
|
||||||
|
ActiveDefragRunning int64 `json:"active_defrag_running"`
|
||||||
|
AllocatorActive int64 `json:"allocator_active"`
|
||||||
|
AllocatorAllocated int64 `json:"allocator_allocated"`
|
||||||
|
AllocatorFragBytes float64 `json:"allocator_frag_bytes"` // for historical reasons this was left as float although redis reports it as an int
|
||||||
|
AllocatorFragRatio float64 `json:"allocator_frag_ratio"`
|
||||||
|
AllocatorResident int64 `json:"allocator_resident"`
|
||||||
|
AllocatorRssBytes int64 `json:"allocator_rss_bytes"`
|
||||||
|
AllocatorRssRatio float64 `json:"allocator_rss_ratio"`
|
||||||
|
AofCurrentRewriteTimeSec int64 `json:"aof_current_rewrite_time_sec"`
|
||||||
|
AofEnabled int64 `json:"aof_enabled"`
|
||||||
|
AofLastBgrewriteStatus string `json:"aof_last_bgrewrite_status"`
|
||||||
|
AofLastCowSize int64 `json:"aof_last_cow_size"`
|
||||||
|
AofLastRewriteTimeSec int64 `json:"aof_last_rewrite_time_sec"`
|
||||||
|
AofLastWriteStatus string `json:"aof_last_write_status"`
|
||||||
|
AofRewriteInProgress int64 `json:"aof_rewrite_in_progress"`
|
||||||
|
AofRewriteScheduled int64 `json:"aof_rewrite_scheduled"`
|
||||||
|
BlockedClients int64 `json:"blocked_clients"`
|
||||||
|
ClientRecentMaxInputBuffer int64 `json:"client_recent_max_input_buffer"`
|
||||||
|
ClientRecentMaxOutputBuffer int64 `json:"client_recent_max_output_buffer"`
|
||||||
|
Clients int64 `json:"clients"`
|
||||||
|
ClientsInTimeoutTable int64 `json:"clients_in_timeout_table"`
|
||||||
|
ClusterEnabled int64 `json:"cluster_enabled"`
|
||||||
|
ConnectedSlaves int64 `json:"connected_slaves"`
|
||||||
|
EvictedKeys int64 `json:"evicted_keys"`
|
||||||
|
ExpireCycleCPUMilliseconds int64 `json:"expire_cycle_cpu_milliseconds"`
|
||||||
|
ExpiredKeys int64 `json:"expired_keys"`
|
||||||
|
ExpiredStalePerc float64 `json:"expired_stale_perc"`
|
||||||
|
ExpiredTimeCapReachedCount int64 `json:"expired_time_cap_reached_count"`
|
||||||
|
InstantaneousInputKbps float64 `json:"instantaneous_input_kbps"`
|
||||||
|
InstantaneousOpsPerSec int64 `json:"instantaneous_ops_per_sec"`
|
||||||
|
InstantaneousOutputKbps float64 `json:"instantaneous_output_kbps"`
|
||||||
|
IoThreadedReadsProcessed int64 `json:"io_threaded_reads_processed"`
|
||||||
|
IoThreadedWritesProcessed int64 `json:"io_threaded_writes_processed"`
|
||||||
|
KeyspaceHits int64 `json:"keyspace_hits"`
|
||||||
|
KeyspaceMisses int64 `json:"keyspace_misses"`
|
||||||
|
LatestForkUsec int64 `json:"latest_fork_usec"`
|
||||||
|
LazyfreePendingObjects int64 `json:"lazyfree_pending_objects"`
|
||||||
|
Loading int64 `json:"loading"`
|
||||||
|
LruClock int64 `json:"lru_clock"`
|
||||||
|
MasterReplOffset int64 `json:"master_repl_offset"`
|
||||||
|
MaxMemory int64 `json:"maxmemory"`
|
||||||
|
MaxMemoryPolicy string `json:"maxmemory_policy"`
|
||||||
|
MemAofBuffer int64 `json:"mem_aof_buffer"`
|
||||||
|
MemClientsNormal int64 `json:"mem_clients_normal"`
|
||||||
|
MemClientsSlaves int64 `json:"mem_clients_slaves"`
|
||||||
|
MemFragmentationBytes int64 `json:"mem_fragmentation_bytes"`
|
||||||
|
MemFragmentationRatio float64 `json:"mem_fragmentation_ratio"`
|
||||||
|
MemNotCountedForEvict int64 `json:"mem_not_counted_for_evict"`
|
||||||
|
MemReplicationBacklog int64 `json:"mem_replication_backlog"`
|
||||||
|
MigrateCachedSockets int64 `json:"migrate_cached_sockets"`
|
||||||
|
ModuleForkInProgress int64 `json:"module_fork_in_progress"`
|
||||||
|
ModuleForkLastCowSize int64 `json:"module_fork_last_cow_size"`
|
||||||
|
NumberOfCachedScripts int64 `json:"number_of_cached_scripts"`
|
||||||
|
PubsubChannels int64 `json:"pubsub_channels"`
|
||||||
|
PubsubPatterns int64 `json:"pubsub_patterns"`
|
||||||
|
RdbBgsaveInProgress int64 `json:"rdb_bgsave_in_progress"`
|
||||||
|
RdbChangesSinceLastSave int64 `json:"rdb_changes_since_last_save"`
|
||||||
|
RdbCurrentBgsaveTimeSec int64 `json:"rdb_current_bgsave_time_sec"`
|
||||||
|
RdbLastBgsaveStatus string `json:"rdb_last_bgsave_status"`
|
||||||
|
RdbLastBgsaveTimeSec int64 `json:"rdb_last_bgsave_time_sec"`
|
||||||
|
RdbLastCowSize int64 `json:"rdb_last_cow_size"`
|
||||||
|
RdbLastSaveTime int64 `json:"rdb_last_save_time"`
|
||||||
|
RdbLastSaveTimeElapsed int64 `json:"rdb_last_save_time_elapsed"`
|
||||||
|
RedisVersion string `json:"redis_version"`
|
||||||
|
RejectedConnections int64 `json:"rejected_connections"`
|
||||||
|
ReplBacklogActive int64 `json:"repl_backlog_active"`
|
||||||
|
ReplBacklogFirstByteOffset int64 `json:"repl_backlog_first_byte_offset"`
|
||||||
|
ReplBacklogHistlen int64 `json:"repl_backlog_histlen"`
|
||||||
|
ReplBacklogSize int64 `json:"repl_backlog_size"`
|
||||||
|
RssOverheadBytes int64 `json:"rss_overhead_bytes"`
|
||||||
|
RssOverheadRatio float64 `json:"rss_overhead_ratio"`
|
||||||
|
SecondReplOffset int64 `json:"second_repl_offset"`
|
||||||
|
SlaveExpiresTrackedKeys int64 `json:"slave_expires_tracked_keys"`
|
||||||
|
SyncFull int64 `json:"sync_full"`
|
||||||
|
SyncPartialErr int64 `json:"sync_partial_err"`
|
||||||
|
SyncPartialOk int64 `json:"sync_partial_ok"`
|
||||||
|
TotalCommandsProcessed int64 `json:"total_commands_processed"`
|
||||||
|
TotalConnectionsReceived int64 `json:"total_connections_received"`
|
||||||
|
TotalNetInputBytes int64 `json:"total_net_input_bytes"`
|
||||||
|
TotalNetOutputBytes int64 `json:"total_net_output_bytes"`
|
||||||
|
TotalReadsProcessed int64 `json:"total_reads_processed"`
|
||||||
|
TotalSystemMemory int64 `json:"total_system_memory"`
|
||||||
|
TotalWritesProcessed int64 `json:"total_writes_processed"`
|
||||||
|
TrackingClients int64 `json:"tracking_clients"`
|
||||||
|
TrackingTotalItems int64 `json:"tracking_total_items"`
|
||||||
|
TrackingTotalKeys int64 `json:"tracking_total_keys"`
|
||||||
|
TrackingTotalPrefixes int64 `json:"tracking_total_prefixes"`
|
||||||
|
UnexpectedErrorReplies int64 `json:"unexpected_error_replies"`
|
||||||
|
Uptime int64 `json:"uptime"`
|
||||||
|
UsedCPUSys float64 `json:"used_cpu_sys"`
|
||||||
|
UsedCPUSysChildren float64 `json:"used_cpu_sys_children"`
|
||||||
|
UsedCPUUser float64 `json:"used_cpu_user"`
|
||||||
|
UsedCPUUserChildren float64 `json:"used_cpu_user_children"`
|
||||||
|
UsedMemory int64 `json:"used_memory"`
|
||||||
|
UsedMemoryDataset int64 `json:"used_memory_dataset"`
|
||||||
|
UsedMemoryDatasetPerc float64 `json:"used_memory_dataset_perc"`
|
||||||
|
UsedMemoryLua int64 `json:"used_memory_lua"`
|
||||||
|
UsedMemoryOverhead int64 `json:"used_memory_overhead"`
|
||||||
|
UsedMemoryPeak int64 `json:"used_memory_peak"`
|
||||||
|
UsedMemoryPeakPerc float64 `json:"used_memory_peak_perc"`
|
||||||
|
UsedMemoryRss int64 `json:"used_memory_rss"`
|
||||||
|
UsedMemoryScripts int64 `json:"used_memory_scripts"`
|
||||||
|
UsedMemoryStartup int64 `json:"used_memory_startup"`
|
||||||
|
}
|
||||||
|
|
||||||
func (r *RedisClient) Do(returnType string, args ...interface{}) (interface{}, error) {
|
func (r *RedisClient) Do(returnType string, args ...interface{}) (interface{}, error) {
|
||||||
rawVal := r.client.Do(args...)
|
rawVal := r.client.Do(args...)
|
||||||
|
|
||||||
|
|
@ -352,6 +464,12 @@ func gatherInfoOutput(
|
||||||
keyspace_hitrate = float64(keyspace_hits) / float64(keyspace_hits+keyspace_misses)
|
keyspace_hitrate = float64(keyspace_hits) / float64(keyspace_hits+keyspace_misses)
|
||||||
}
|
}
|
||||||
fields["keyspace_hitrate"] = keyspace_hitrate
|
fields["keyspace_hitrate"] = keyspace_hitrate
|
||||||
|
|
||||||
|
o := RedisFieldTypes{}
|
||||||
|
|
||||||
|
setStructFieldsFromObject(fields, &o)
|
||||||
|
setExistingFieldsFromStruct(fields, &o)
|
||||||
|
|
||||||
acc.AddFields("redis", fields, tags)
|
acc.AddFields("redis", fields, tags)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -479,3 +597,115 @@ func init() {
|
||||||
return &Redis{}
|
return &Redis{}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setExistingFieldsFromStruct(fields map[string]interface{}, o *RedisFieldTypes) {
|
||||||
|
val := reflect.ValueOf(o).Elem()
|
||||||
|
typ := val.Type()
|
||||||
|
|
||||||
|
for key := range fields {
|
||||||
|
if _, exists := fields[key]; exists {
|
||||||
|
for i := 0; i < typ.NumField(); i++ {
|
||||||
|
f := typ.Field(i)
|
||||||
|
jsonFieldName := f.Tag.Get("json")
|
||||||
|
if jsonFieldName == key {
|
||||||
|
fields[key] = val.Field(i).Interface()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setStructFieldsFromObject(fields map[string]interface{}, o *RedisFieldTypes) {
|
||||||
|
val := reflect.ValueOf(o).Elem()
|
||||||
|
typ := val.Type()
|
||||||
|
|
||||||
|
for key, value := range fields {
|
||||||
|
if _, exists := fields[key]; exists {
|
||||||
|
for i := 0; i < typ.NumField(); i++ {
|
||||||
|
f := typ.Field(i)
|
||||||
|
jsonFieldName := f.Tag.Get("json")
|
||||||
|
if jsonFieldName == key {
|
||||||
|
structFieldValue := val.Field(i)
|
||||||
|
structFieldValue.Set(coerceType(value, structFieldValue.Type()))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func coerceType(value interface{}, typ reflect.Type) reflect.Value {
|
||||||
|
switch sourceType := value.(type) {
|
||||||
|
case bool:
|
||||||
|
switch typ.Kind() {
|
||||||
|
case reflect.String:
|
||||||
|
if sourceType {
|
||||||
|
value = "true"
|
||||||
|
} else {
|
||||||
|
value = "false"
|
||||||
|
}
|
||||||
|
case reflect.Int64:
|
||||||
|
if sourceType {
|
||||||
|
value = int64(1)
|
||||||
|
} else {
|
||||||
|
value = int64(0)
|
||||||
|
}
|
||||||
|
case reflect.Float64:
|
||||||
|
if sourceType {
|
||||||
|
value = float64(1)
|
||||||
|
} else {
|
||||||
|
value = float64(0)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unhandled destination type %s", typ.Kind().String()))
|
||||||
|
}
|
||||||
|
case int, int8, int16, int32, int64:
|
||||||
|
switch typ.Kind() {
|
||||||
|
case reflect.String:
|
||||||
|
value = fmt.Sprintf("%d", value)
|
||||||
|
case reflect.Int64:
|
||||||
|
// types match
|
||||||
|
case reflect.Float64:
|
||||||
|
value = float64(reflect.ValueOf(sourceType).Int())
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unhandled destination type %s", typ.Kind().String()))
|
||||||
|
}
|
||||||
|
case uint, uint8, uint16, uint32, uint64:
|
||||||
|
switch typ.Kind() {
|
||||||
|
case reflect.String:
|
||||||
|
value = fmt.Sprintf("%d", value)
|
||||||
|
case reflect.Int64:
|
||||||
|
// types match
|
||||||
|
case reflect.Float64:
|
||||||
|
value = float64(reflect.ValueOf(sourceType).Uint())
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unhandled destination type %s", typ.Kind().String()))
|
||||||
|
}
|
||||||
|
case float32, float64:
|
||||||
|
switch typ.Kind() {
|
||||||
|
case reflect.String:
|
||||||
|
value = fmt.Sprintf("%f", value)
|
||||||
|
case reflect.Int64:
|
||||||
|
value = int64(reflect.ValueOf(sourceType).Float())
|
||||||
|
case reflect.Float64:
|
||||||
|
// types match
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unhandled destination type %s", typ.Kind().String()))
|
||||||
|
}
|
||||||
|
case string:
|
||||||
|
switch typ.Kind() {
|
||||||
|
case reflect.String:
|
||||||
|
// types match
|
||||||
|
case reflect.Int64:
|
||||||
|
value, _ = strconv.ParseInt(value.(string), 10, 64)
|
||||||
|
case reflect.Float64:
|
||||||
|
value, _ = strconv.ParseFloat(value.(string), 64)
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unhandled destination type %s", typ.Kind().String()))
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unhandled source type %T", sourceType))
|
||||||
|
}
|
||||||
|
return reflect.ValueOf(value)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -138,7 +138,60 @@ func TestRedis_ParseMetrics(t *testing.T) {
|
||||||
"used_cpu_sys_children": float64(0.00),
|
"used_cpu_sys_children": float64(0.00),
|
||||||
"used_cpu_user_children": float64(0.00),
|
"used_cpu_user_children": float64(0.00),
|
||||||
"keyspace_hitrate": float64(0.50),
|
"keyspace_hitrate": float64(0.50),
|
||||||
"redis_version": "2.8.9",
|
"redis_version": "6.0.9",
|
||||||
|
"active_defrag_hits": int64(0),
|
||||||
|
"active_defrag_key_hits": int64(0),
|
||||||
|
"active_defrag_key_misses": int64(0),
|
||||||
|
"active_defrag_misses": int64(0),
|
||||||
|
"active_defrag_running": int64(0),
|
||||||
|
"allocator_active": int64(1022976),
|
||||||
|
"allocator_allocated": int64(1019632),
|
||||||
|
"allocator_frag_bytes": float64(3344),
|
||||||
|
"allocator_frag_ratio": float64(1.00),
|
||||||
|
"allocator_resident": int64(1022976),
|
||||||
|
"allocator_rss_bytes": int64(0),
|
||||||
|
"allocator_rss_ratio": float64(1.00),
|
||||||
|
"aof_last_cow_size": int64(0),
|
||||||
|
"client_recent_max_input_buffer": int64(16),
|
||||||
|
"client_recent_max_output_buffer": int64(0),
|
||||||
|
"clients_in_timeout_table": int64(0),
|
||||||
|
"cluster_enabled": int64(0),
|
||||||
|
"expire_cycle_cpu_milliseconds": int64(669),
|
||||||
|
"expired_stale_perc": float64(0.00),
|
||||||
|
"expired_time_cap_reached_count": int64(0),
|
||||||
|
"io_threaded_reads_processed": int64(0),
|
||||||
|
"io_threaded_writes_processed": int64(0),
|
||||||
|
"total_reads_processed": int64(31),
|
||||||
|
"total_writes_processed": int64(17),
|
||||||
|
"lazyfree_pending_objects": int64(0),
|
||||||
|
"maxmemory": int64(0),
|
||||||
|
"maxmemory_policy": string("noeviction"),
|
||||||
|
"mem_aof_buffer": int64(0),
|
||||||
|
"mem_clients_normal": int64(17440),
|
||||||
|
"mem_clients_slaves": int64(0),
|
||||||
|
"mem_fragmentation_bytes": int64(41232),
|
||||||
|
"mem_not_counted_for_evict": int64(0),
|
||||||
|
"mem_replication_backlog": int64(0),
|
||||||
|
"rss_overhead_bytes": int64(37888),
|
||||||
|
"rss_overhead_ratio": float64(1.04),
|
||||||
|
"total_system_memory": int64(17179869184),
|
||||||
|
"used_memory_dataset": int64(47088),
|
||||||
|
"used_memory_overhead": int64(1019152),
|
||||||
|
"used_memory_scripts": int64(0),
|
||||||
|
"used_memory_startup": int64(1001712),
|
||||||
|
"migrate_cached_sockets": int64(0),
|
||||||
|
"module_fork_in_progress": int64(0),
|
||||||
|
"module_fork_last_cow_size": int64(0),
|
||||||
|
"number_of_cached_scripts": int64(0),
|
||||||
|
"rdb_last_cow_size": int64(0),
|
||||||
|
"slave_expires_tracked_keys": int64(0),
|
||||||
|
"unexpected_error_replies": int64(0),
|
||||||
|
"total_net_input_bytes": int64(381),
|
||||||
|
"total_net_output_bytes": int64(71521),
|
||||||
|
"tracking_clients": int64(0),
|
||||||
|
"tracking_total_items": int64(0),
|
||||||
|
"tracking_total_keys": int64(0),
|
||||||
|
"tracking_total_prefixes": int64(0),
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have to test rdb_last_save_time_offset manually because the value is based on the time when gathered
|
// We have to test rdb_last_save_time_offset manually because the value is based on the time when gathered
|
||||||
|
|
@ -210,26 +263,110 @@ func TestRedis_ParseMetrics(t *testing.T) {
|
||||||
acc.AssertContainsTaggedFields(t, "redis_replication", replicationFields, replicationTags)
|
acc.AssertContainsTaggedFields(t, "redis_replication", replicationFields, replicationTags)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRedis_ParseFloatOnInts(t *testing.T) {
|
||||||
|
var acc testutil.Accumulator
|
||||||
|
tags := map[string]string{"host": "redis.net"}
|
||||||
|
rdr := bufio.NewReader(strings.NewReader(strings.Replace(testOutput, "mem_fragmentation_ratio:0.81", "mem_fragmentation_ratio:1", 1)))
|
||||||
|
err := gatherInfoOutput(rdr, &acc, tags)
|
||||||
|
require.NoError(t, err)
|
||||||
|
var m *testutil.Metric
|
||||||
|
for i := range acc.Metrics {
|
||||||
|
if _, ok := acc.Metrics[i].Fields["mem_fragmentation_ratio"]; ok {
|
||||||
|
m = acc.Metrics[i]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
require.NotNil(t, m)
|
||||||
|
fragRatio, ok := m.Fields["mem_fragmentation_ratio"]
|
||||||
|
require.True(t, ok)
|
||||||
|
require.IsType(t, float64(0.0), fragRatio)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRedis_ParseIntOnFloats(t *testing.T) {
|
||||||
|
var acc testutil.Accumulator
|
||||||
|
tags := map[string]string{"host": "redis.net"}
|
||||||
|
rdr := bufio.NewReader(strings.NewReader(strings.Replace(testOutput, "clients_in_timeout_table:0", "clients_in_timeout_table:0.0", 1)))
|
||||||
|
err := gatherInfoOutput(rdr, &acc, tags)
|
||||||
|
require.NoError(t, err)
|
||||||
|
var m *testutil.Metric
|
||||||
|
for i := range acc.Metrics {
|
||||||
|
if _, ok := acc.Metrics[i].Fields["clients_in_timeout_table"]; ok {
|
||||||
|
m = acc.Metrics[i]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
require.NotNil(t, m)
|
||||||
|
clientsInTimeout, ok := m.Fields["clients_in_timeout_table"]
|
||||||
|
require.True(t, ok)
|
||||||
|
require.IsType(t, int64(0), clientsInTimeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRedis_ParseStringOnInts(t *testing.T) {
|
||||||
|
var acc testutil.Accumulator
|
||||||
|
tags := map[string]string{"host": "redis.net"}
|
||||||
|
rdr := bufio.NewReader(strings.NewReader(strings.Replace(testOutput, "maxmemory_policy:no-eviction", "maxmemory_policy:1", 1)))
|
||||||
|
err := gatherInfoOutput(rdr, &acc, tags)
|
||||||
|
require.NoError(t, err)
|
||||||
|
var m *testutil.Metric
|
||||||
|
for i := range acc.Metrics {
|
||||||
|
if _, ok := acc.Metrics[i].Fields["maxmemory_policy"]; ok {
|
||||||
|
m = acc.Metrics[i]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
require.NotNil(t, m)
|
||||||
|
maxmemoryPolicy, ok := m.Fields["maxmemory_policy"]
|
||||||
|
require.True(t, ok)
|
||||||
|
require.IsType(t, string(""), maxmemoryPolicy)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRedis_ParseIntOnString(t *testing.T) {
|
||||||
|
var acc testutil.Accumulator
|
||||||
|
tags := map[string]string{"host": "redis.net"}
|
||||||
|
rdr := bufio.NewReader(strings.NewReader(strings.Replace(testOutput, "clients_in_timeout_table:0", `clients_in_timeout_table:""`, 1)))
|
||||||
|
err := gatherInfoOutput(rdr, &acc, tags)
|
||||||
|
require.NoError(t, err)
|
||||||
|
var m *testutil.Metric
|
||||||
|
for i := range acc.Metrics {
|
||||||
|
if _, ok := acc.Metrics[i].Fields["clients_in_timeout_table"]; ok {
|
||||||
|
m = acc.Metrics[i]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
require.NotNil(t, m)
|
||||||
|
clientsInTimeout, ok := m.Fields["clients_in_timeout_table"]
|
||||||
|
require.True(t, ok)
|
||||||
|
require.IsType(t, int64(0), clientsInTimeout)
|
||||||
|
}
|
||||||
|
|
||||||
const testOutput = `# Server
|
const testOutput = `# Server
|
||||||
redis_version:2.8.9
|
redis_version:6.0.9
|
||||||
redis_git_sha1:00000000
|
redis_git_sha1:00000000
|
||||||
redis_git_dirty:0
|
redis_git_dirty:0
|
||||||
redis_build_id:9ccc8119ea98f6e1
|
redis_build_id:26c3229b35eb3beb
|
||||||
redis_mode:standalone
|
redis_mode:standalone
|
||||||
os:Darwin 14.1.0 x86_64
|
os:Darwin 19.6.0 x86_64
|
||||||
arch_bits:64
|
arch_bits:64
|
||||||
multiplexing_api:kqueue
|
multiplexing_api:kqueue
|
||||||
|
atomicvar_api:atomic-builtin
|
||||||
gcc_version:4.2.1
|
gcc_version:4.2.1
|
||||||
process_id:40235
|
process_id:46677
|
||||||
run_id:37d020620aadf0627282c0f3401405d774a82664
|
run_id:5d6bf38087b23e48f1a59b7aca52e2b55438b02f
|
||||||
tcp_port:6379
|
tcp_port:6379
|
||||||
uptime_in_seconds:238
|
uptime_in_seconds:238
|
||||||
uptime_in_days:0
|
uptime_in_days:0
|
||||||
hz:10
|
hz:10
|
||||||
|
configured_hz:10
|
||||||
lru_clock:2364819
|
lru_clock:2364819
|
||||||
|
executable:/usr/local/opt/redis/bin/redis-server
|
||||||
config_file:/usr/local/etc/redis.conf
|
config_file:/usr/local/etc/redis.conf
|
||||||
|
io_threads_active:0
|
||||||
|
|
||||||
# Clients
|
# Clients
|
||||||
|
client_recent_max_input_buffer:16
|
||||||
|
client_recent_max_output_buffer:0
|
||||||
|
tracking_clients:0
|
||||||
|
clients_in_timeout_table:0
|
||||||
connected_clients:1
|
connected_clients:1
|
||||||
client_longest_output_list:0
|
client_longest_output_list:0
|
||||||
client_biggest_input_buf:0
|
client_biggest_input_buf:0
|
||||||
|
|
@ -239,13 +376,43 @@ blocked_clients:0
|
||||||
used_memory:1003936
|
used_memory:1003936
|
||||||
used_memory_human:980.41K
|
used_memory_human:980.41K
|
||||||
used_memory_rss:811008
|
used_memory_rss:811008
|
||||||
|
used_memory_rss_human:1.01M
|
||||||
used_memory_peak:1003936
|
used_memory_peak:1003936
|
||||||
used_memory_peak_human:980.41K
|
used_memory_peak_human:980.41K
|
||||||
used_memory_lua:33792
|
|
||||||
mem_fragmentation_ratio:0.81
|
|
||||||
mem_allocator:libc
|
|
||||||
used_memory_peak_perc:93.58%
|
used_memory_peak_perc:93.58%
|
||||||
|
used_memory_overhead:1019152
|
||||||
|
used_memory_startup:1001712
|
||||||
|
used_memory_dataset:47088
|
||||||
used_memory_dataset_perc:20.27%
|
used_memory_dataset_perc:20.27%
|
||||||
|
allocator_allocated:1019632
|
||||||
|
allocator_active:1022976
|
||||||
|
allocator_resident:1022976
|
||||||
|
total_system_memory:17179869184
|
||||||
|
total_system_memory_human:16.00G
|
||||||
|
used_memory_lua:33792
|
||||||
|
used_memory_lua_human:37.00K
|
||||||
|
used_memory_scripts:0
|
||||||
|
used_memory_scripts_human:0B
|
||||||
|
number_of_cached_scripts:0
|
||||||
|
maxmemory:0
|
||||||
|
maxmemory_human:0B
|
||||||
|
maxmemory_policy:noeviction
|
||||||
|
allocator_frag_ratio:1.00
|
||||||
|
allocator_frag_bytes:3344
|
||||||
|
allocator_rss_ratio:1.00
|
||||||
|
allocator_rss_bytes:0
|
||||||
|
rss_overhead_ratio:1.04
|
||||||
|
rss_overhead_bytes:37888
|
||||||
|
mem_fragmentation_ratio:0.81
|
||||||
|
mem_fragmentation_bytes:41232
|
||||||
|
mem_not_counted_for_evict:0
|
||||||
|
mem_replication_backlog:0
|
||||||
|
mem_clients_slaves:0
|
||||||
|
mem_clients_normal:17440
|
||||||
|
mem_aof_buffer:0
|
||||||
|
mem_allocator:libc
|
||||||
|
active_defrag_running:0
|
||||||
|
lazyfree_pending_objects:0
|
||||||
|
|
||||||
# Persistence
|
# Persistence
|
||||||
loading:0
|
loading:0
|
||||||
|
|
@ -255,6 +422,7 @@ rdb_last_save_time:1428427941
|
||||||
rdb_last_bgsave_status:ok
|
rdb_last_bgsave_status:ok
|
||||||
rdb_last_bgsave_time_sec:-1
|
rdb_last_bgsave_time_sec:-1
|
||||||
rdb_current_bgsave_time_sec:-1
|
rdb_current_bgsave_time_sec:-1
|
||||||
|
rdb_last_cow_size:0
|
||||||
aof_enabled:0
|
aof_enabled:0
|
||||||
aof_rewrite_in_progress:0
|
aof_rewrite_in_progress:0
|
||||||
aof_rewrite_scheduled:0
|
aof_rewrite_scheduled:0
|
||||||
|
|
@ -262,11 +430,16 @@ aof_last_rewrite_time_sec:-1
|
||||||
aof_current_rewrite_time_sec:-1
|
aof_current_rewrite_time_sec:-1
|
||||||
aof_last_bgrewrite_status:ok
|
aof_last_bgrewrite_status:ok
|
||||||
aof_last_write_status:ok
|
aof_last_write_status:ok
|
||||||
|
aof_last_cow_size:0
|
||||||
|
module_fork_in_progress:0
|
||||||
|
module_fork_last_cow_size:0
|
||||||
|
|
||||||
# Stats
|
# Stats
|
||||||
total_connections_received:2
|
total_connections_received:2
|
||||||
total_commands_processed:1
|
total_commands_processed:1
|
||||||
instantaneous_ops_per_sec:0
|
instantaneous_ops_per_sec:0
|
||||||
|
total_net_input_bytes:381
|
||||||
|
total_net_output_bytes:71521
|
||||||
instantaneous_input_kbps:876.16
|
instantaneous_input_kbps:876.16
|
||||||
instantaneous_output_kbps:3010.23
|
instantaneous_output_kbps:3010.23
|
||||||
rejected_connections:0
|
rejected_connections:0
|
||||||
|
|
@ -274,12 +447,29 @@ sync_full:0
|
||||||
sync_partial_ok:0
|
sync_partial_ok:0
|
||||||
sync_partial_err:0
|
sync_partial_err:0
|
||||||
expired_keys:0
|
expired_keys:0
|
||||||
|
expired_stale_perc:0.00
|
||||||
|
expired_time_cap_reached_count:0
|
||||||
|
expire_cycle_cpu_milliseconds:669
|
||||||
evicted_keys:0
|
evicted_keys:0
|
||||||
keyspace_hits:1
|
keyspace_hits:1
|
||||||
keyspace_misses:1
|
keyspace_misses:1
|
||||||
pubsub_channels:0
|
pubsub_channels:0
|
||||||
pubsub_patterns:0
|
pubsub_patterns:0
|
||||||
latest_fork_usec:0
|
latest_fork_usec:0
|
||||||
|
migrate_cached_sockets:0
|
||||||
|
slave_expires_tracked_keys:0
|
||||||
|
active_defrag_hits:0
|
||||||
|
active_defrag_misses:0
|
||||||
|
active_defrag_key_hits:0
|
||||||
|
active_defrag_key_misses:0
|
||||||
|
tracking_total_keys:0
|
||||||
|
tracking_total_items:0
|
||||||
|
tracking_total_prefixes:0
|
||||||
|
unexpected_error_replies:0
|
||||||
|
total_reads_processed:31
|
||||||
|
total_writes_processed:17
|
||||||
|
io_threaded_reads_processed:0
|
||||||
|
io_threaded_writes_processed:0
|
||||||
|
|
||||||
# Replication
|
# Replication
|
||||||
role:master
|
role:master
|
||||||
|
|
@ -301,6 +491,9 @@ used_cpu_user:0.05
|
||||||
used_cpu_sys_children:0.00
|
used_cpu_sys_children:0.00
|
||||||
used_cpu_user_children:0.00
|
used_cpu_user_children:0.00
|
||||||
|
|
||||||
|
# Cluster
|
||||||
|
cluster_enabled:0
|
||||||
|
|
||||||
# Commandstats
|
# Commandstats
|
||||||
cmdstat_set:calls=261265,usec=1634157,usec_per_call=6.25
|
cmdstat_set:calls=261265,usec=1634157,usec_per_call=6.25
|
||||||
cmdstat_command:calls=1,usec=990,usec_per_call=990.00
|
cmdstat_command:calls=1,usec=990,usec_per_call=990.00
|
||||||
|
|
@ -308,5 +501,4 @@ cmdstat_command:calls=1,usec=990,usec_per_call=990.00
|
||||||
# Keyspace
|
# Keyspace
|
||||||
db0:keys=2,expires=0,avg_ttl=0
|
db0:keys=2,expires=0,avg_ttl=0
|
||||||
|
|
||||||
(error) ERR unknown command 'eof'
|
(error) ERR unknown command 'eof'`
|
||||||
`
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue