Skip to content

Commit 1873544

Browse files
committed
Adding addional stats
1 parent 60dca64 commit 1873544

File tree

10 files changed

+556
-180
lines changed

10 files changed

+556
-180
lines changed

README.md

Lines changed: 127 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,40 @@ A powerful, k9s-inspired Terminal User Interface (TUI) Redis/Valkey client built
1111

1212
## 🌟 Features
1313

14-
- 🎯 Multi-View Navigation
15-
- 🔧 Advanced Key Management
16-
- 📊 Real-time Monitoring
17-
- 💻 Integrated CLI
18-
- ⚙️ Configuration Management
19-
- 🎨 User Experience
14+
### 🎯 Multi-View Navigation
15+
- **Keys View**: Advanced key browsing with filtering, type display, and TTL management
16+
- **Info View**: Comprehensive Redis server information and statistics
17+
- **Monitor View**: Real-time metrics with client connections, command statistics, slow queries, and cluster nodes
18+
- **CLI View**: Integrated Redis CLI with command history and scrollable output
19+
- **Config View**: Runtime configuration management
20+
- **Help View**: Interactive help and keyboard shortcuts
21+
22+
### 🔧 Advanced Key Management
23+
- Smart key filtering and searching
24+
- Multiple data type support (String, Hash, List, Set, ZSet, etc.)
25+
- Batch operations and key expiration management
26+
- Memory usage and TTL information display
27+
28+
### 📊 Real-time Monitoring
29+
- **Client Connections**: Active clients, total connections, rejected connections
30+
- **Memory Usage**: Used memory and RSS with human-readable formatting
31+
- **Command Statistics**: Total commands, operations per second, hit/miss rates
32+
- **Slow Query Log**: Monitor slow-running operations
33+
- **Cluster Nodes**: Detailed node information in table format for cluster setups
34+
35+
### 💻 Integrated CLI
36+
- Full Redis command support with syntax highlighting
37+
- Command history with up/down arrow navigation
38+
- Scrollable output with Page Up/Down support
39+
- Tab to switch focus between input and output areas
40+
41+
### ⚙️ Configuration Management
42+
- **TLS/SSL Support**: Secure connections with certificate authentication
43+
- JSON-based configuration with environment variable support
44+
- Runtime configuration updates
45+
- Connection pooling and timeout management
46+
47+
### 🎨 User Experience
2048

2149
## 🚀 Quick Start
2250

@@ -107,25 +135,62 @@ Examples:
107135

108136
### Configuration
109137

110-
Create `~/.redis-cli-dashboard/config.yaml`:
111-
112-
```yaml
113-
redis:
114-
host: "localhost"
115-
port: 6379
116-
password: ""
117-
db: 0
118-
timeout: 5000
119-
pool_size: 10
120-
121-
ui:
122-
theme: "default"
123-
refresh_interval: 1000
124-
max_keys: 1000
125-
show_memory: true
126-
show_ttl: true
138+
Create `~/.redis-cli-dashboard/config.json`:
139+
140+
```json
141+
{
142+
"redis": {
143+
"host": "localhost",
144+
"port": 6379,
145+
"password": "",
146+
"db": 0,
147+
"timeout": 5000,
148+
"pool_size": 10,
149+
"tls": {
150+
"enabled": false,
151+
"cert_file": "",
152+
"key_file": "",
153+
"ca_file": "",
154+
"insecure_skip_verify": false
155+
}
156+
},
157+
"ui": {
158+
"theme": "default",
159+
"refresh_interval": 1000,
160+
"max_keys": 1000,
161+
"show_memory": true,
162+
"show_ttl": true
163+
}
164+
}
127165
```
128166

167+
### TLS/SSL Configuration
168+
169+
For secure Redis connections, enable TLS in your configuration:
170+
171+
```json
172+
{
173+
"redis": {
174+
"host": "secure-redis.example.com",
175+
"port": 6380,
176+
"tls": {
177+
"enabled": true,
178+
"cert_file": "/path/to/client.crt",
179+
"key_file": "/path/to/client.key",
180+
"ca_file": "/path/to/ca.crt",
181+
"insecure_skip_verify": false
182+
}
183+
}
184+
}
185+
```
186+
187+
**TLS Options:**
188+
- `enabled`: Enable/disable TLS connection
189+
- `cert_file`: Path to client certificate file (optional)
190+
- `key_file`: Path to client private key file (optional)
191+
- `ca_file`: Path to CA certificate file (optional)
192+
- `insecure_skip_verify`: Skip certificate verification (not recommended for production)
193+
129194
## 🎮 Navigation & Controls
130195

131196
### Global Navigation
@@ -148,26 +213,60 @@ ui:
148213
| `↑/↓` | Navigate keys |
149214
| `Enter` | View key details |
150215
| `/` | Focus filter input |
151-
| `c` | Focus command input |
152216
| `r` | Refresh key list |
153217
| `d` | Delete selected key |
154218
| `e` | Edit selected key |
155219
| `t` | Set/modify TTL |
220+
| `Mouse Click` | Select key (mouse interaction enabled) |
221+
222+
**Filter Controls:**
223+
- `Ctrl+L` - Clear filter input
224+
- `Ctrl+C` - Clear filter and return to table
225+
- `ESC` - Return to table without clearing filter
226+
- **Mouse clicks** work properly on filtered results to select keys
227+
- **Arrow key navigation** works correctly after filtering
156228

157229
### CLI View
158230
| Key | Action |
159231
|-----|--------|
160232
| `Enter` | Execute command |
161-
| `↑/↓` | Navigate command history |
162-
| `Ctrl+L` | Clear screen |
163-
| `Tab` | Command completion (if available) |
233+
| `↑/↓` | Navigate command history (when input focused) / Scroll output (when output focused) |
234+
| `Tab` | Switch focus between input and output |
235+
| `Ctrl+L` | Clear output screen |
236+
| `PgUp/PgDn` | Scroll output by 10 lines (when output has focus) |
237+
| `Home/End` | Jump to beginning/end of output (when output has focus) |
238+
| `Mouse Scroll` | Scroll output with mouse wheel |
239+
240+
**Focus Management:**
241+
- **Input field** is focused by default for command entry
242+
- **Arrow keys** navigate command history only when input is focused
243+
- Press `Tab` to switch focus to output area for scrolling
244+
- **Arrow keys** scroll output line by line when output is focused
245+
- **Page Up/Down, Home/End** work for navigation when output is focused
246+
- Mouse scrolling works in output area regardless of focus
164247

165248
### Monitor View
166249
| Key | Action |
167250
|-----|--------|
168-
| `s` | Start/stop monitoring |
251+
| `s` | Start/stop real-time monitoring |
169252
| `c` | Clear screen |
170253
| `r` | Refresh metrics |
254+
| `↑/↓` | Scroll through metrics (when monitoring stopped) |
255+
256+
**Monitor Features:**
257+
- Real-time client connection tracking
258+
- Command statistics with hit/miss rates
259+
- Slow query log monitoring
260+
- Cluster nodes table with role and status
261+
- Memory usage with human-readable formatting
262+
263+
**Important Notes:**
264+
- Number keys (1-6) work as navigation shortcuts only when not typing in input fields
265+
- Filter inputs correctly handle numbers without triggering view switches
266+
- CLI output scrolling works properly when output area has focus (use Tab to switch focus)
267+
- Mouse interaction is enabled for key selection in Keys view, including filtered results
268+
- Filter input can be cleared quickly with Ctrl+L or Ctrl+C shortcuts
269+
- Arrow key navigation works correctly in filtered key lists
171270

172271

173272

config.example.json

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,24 @@
11
{
22
"redis": {
33
"host": "localhost",
4-
"port": 6379,
4+
"port": 6380,
55
"password": "",
6-
"db": 0
6+
"db": 0,
7+
"timeout": 5000,
8+
"pool_size": 10,
9+
"tls": {
10+
"enabled": true,
11+
"cert_file": "/path/to/client.crt",
12+
"key_file": "/path/to/client.key",
13+
"ca_file": "/path/to/ca.crt",
14+
"insecure_skip_verify": false
15+
}
716
},
817
"ui": {
9-
"theme": "dark",
10-
"refresh_ms": 1000
18+
"theme": "default",
19+
"refresh_interval": 1000,
20+
"max_keys": 1000,
21+
"show_memory": true,
22+
"show_ttl": true
1123
}
1224
}

internal/config/config.go

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,22 @@ type Config struct {
1515

1616
// RedisConfig holds Redis connection configuration
1717
type RedisConfig struct {
18-
Host string `json:"host"`
19-
Port int `json:"port"`
20-
Password string `json:"password"`
21-
DB int `json:"db"`
22-
Timeout int `json:"timeout"`
23-
PoolSize int `json:"pool_size"`
18+
Host string `json:"host"`
19+
Port int `json:"port"`
20+
Password string `json:"password"`
21+
DB int `json:"db"`
22+
Timeout int `json:"timeout"`
23+
PoolSize int `json:"pool_size"`
24+
TLS TLSConfig `json:"tls"`
25+
}
26+
27+
// TLSConfig holds TLS configuration
28+
type TLSConfig struct {
29+
Enabled bool `json:"enabled"`
30+
CertFile string `json:"cert_file"`
31+
KeyFile string `json:"key_file"`
32+
CAFile string `json:"ca_file"`
33+
InsecureSkipVerify bool `json:"insecure_skip_verify"`
2434
}
2535

2636
// UIConfig holds UI configuration
@@ -42,6 +52,13 @@ func Default() *Config {
4252
DB: 0,
4353
Timeout: 5000,
4454
PoolSize: 10,
55+
TLS: TLSConfig{
56+
Enabled: false,
57+
CertFile: "",
58+
KeyFile: "",
59+
CAFile: "",
60+
InsecureSkipVerify: false,
61+
},
4562
},
4663
UI: UIConfig{
4764
Theme: "default",

internal/redis/client.go

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ package redis
22

33
import (
44
"context"
5+
"crypto/tls"
6+
"crypto/x509"
57
"fmt"
8+
"io/ioutil"
69
"strconv"
710
"strings"
811
"time"
@@ -20,11 +23,44 @@ type Client struct {
2023

2124
// New creates a new Redis client
2225
func New(cfg *config.RedisConfig) (*Client, error) {
23-
rdb := redis.NewClient(&redis.Options{
26+
opts := &redis.Options{
2427
Addr: fmt.Sprintf("%s:%d", cfg.Host, cfg.Port),
2528
Password: cfg.Password,
2629
DB: cfg.DB,
27-
})
30+
}
31+
32+
// Configure TLS if enabled
33+
if cfg.TLS.Enabled {
34+
tlsConfig := &tls.Config{
35+
InsecureSkipVerify: cfg.TLS.InsecureSkipVerify,
36+
}
37+
38+
// Load client certificate if provided
39+
if cfg.TLS.CertFile != "" && cfg.TLS.KeyFile != "" {
40+
cert, err := tls.LoadX509KeyPair(cfg.TLS.CertFile, cfg.TLS.KeyFile)
41+
if err != nil {
42+
return nil, fmt.Errorf("failed to load client certificate: %w", err)
43+
}
44+
tlsConfig.Certificates = []tls.Certificate{cert}
45+
}
46+
47+
// Load CA certificate if provided
48+
if cfg.TLS.CAFile != "" {
49+
caCert, err := ioutil.ReadFile(cfg.TLS.CAFile)
50+
if err != nil {
51+
return nil, fmt.Errorf("failed to read CA certificate: %w", err)
52+
}
53+
caCertPool := x509.NewCertPool()
54+
if !caCertPool.AppendCertsFromPEM(caCert) {
55+
return nil, fmt.Errorf("failed to parse CA certificate")
56+
}
57+
tlsConfig.RootCAs = caCertPool
58+
}
59+
60+
opts.TLSConfig = tlsConfig
61+
}
62+
63+
rdb := redis.NewClient(opts)
2864

2965
ctx := context.Background()
3066

@@ -68,6 +104,11 @@ func (c *Client) ObjectEncoding(key string) (string, error) {
68104
return c.rdb.ObjectEncoding(c.ctx, key).Result()
69105
}
70106

107+
// DBSize returns the number of keys in the current database
108+
func (c *Client) DBSize() (int64, error) {
109+
return c.rdb.DBSize(c.ctx).Result()
110+
}
111+
71112
// GetKeys returns all keys matching the pattern
72113
func (c *Client) GetKeys(pattern string) ([]string, error) {
73114
if pattern == "" {
@@ -316,3 +357,8 @@ type Metrics struct {
316357
InstantaneousOpsPerSec int64
317358
UptimeInSeconds int64
318359
}
360+
361+
// ClusterNodes returns cluster nodes information
362+
func (c *Client) ClusterNodes() (string, error) {
363+
return c.rdb.ClusterNodes(c.ctx).Result()
364+
}

0 commit comments

Comments
 (0)