redis_web_manager 0.1.8 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +6 -6
- data/README.md +1 -2
- data/app/controllers/redis_web_manager/keys_controller.rb +33 -14
- data/app/helpers/redis_web_manager/application_helper.rb +1 -1
- data/app/helpers/redis_web_manager/keys_helper.rb +33 -0
- data/app/views/redis_web_manager/keys/_search.html.erb +31 -0
- data/app/views/redis_web_manager/keys/index.html.erb +8 -10
- data/app/views/redis_web_manager/keys/show.html.erb +1 -1
- data/lib/redis_web_manager/info.rb +2 -6
- data/lib/redis_web_manager/version.rb +1 -1
- data/spec/controllers/redis_web_manager/keys_controller_spec.rb +9 -1
- data/spec/helpers/application_helper_spec.rb +2 -2
- data/spec/helpers/keys_helper_spec.rb +39 -0
- data/spec/redis_web_manager_info_spec.rb +1 -4
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 625fca933d689410a7db50bb4108654ad7953f055825b46a13f8fd40e8833660
|
4
|
+
data.tar.gz: 280d3f28e6d82c33dff79a28190c878eefed38d939ce9ad9a2b3da634241085f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b70d680f8dd17128e020fc872717077012bb8fc1f13be495b4c2b5baa2b81f76ee76b624647fa74356325fcc25cf49ca78c2b2a107d9951acf7d9dbbc646dc54
|
7
|
+
data.tar.gz: f138a669c0d71f1afbba53db6c2a3657f30f756e0a3100a2926f851b39b204be0f62c654560cd4c3b2d7a973ee92bcc8bd573ca231364e0601d6b16d5d236dda
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
redis_web_manager (0.1.
|
4
|
+
redis_web_manager (0.1.9)
|
5
5
|
pagy (~> 3.7)
|
6
6
|
rails (>= 5.2, < 7)
|
7
7
|
redis (~> 4.1.0)
|
@@ -65,7 +65,7 @@ GEM
|
|
65
65
|
tzinfo (~> 1.1)
|
66
66
|
zeitwerk (~> 2.2)
|
67
67
|
builder (3.2.4)
|
68
|
-
concurrent-ruby (1.1.
|
68
|
+
concurrent-ruby (1.1.6)
|
69
69
|
coveralls (0.8.23)
|
70
70
|
json (>= 1.8, < 3)
|
71
71
|
simplecov (~> 0.16.1)
|
@@ -94,10 +94,10 @@ GEM
|
|
94
94
|
mini_portile2 (2.4.0)
|
95
95
|
minitest (5.14.0)
|
96
96
|
nio4r (2.5.2)
|
97
|
-
nokogiri (1.10.
|
97
|
+
nokogiri (1.10.8)
|
98
98
|
mini_portile2 (~> 2.4.0)
|
99
|
-
pagy (3.7.
|
100
|
-
rack (2.
|
99
|
+
pagy (3.7.3)
|
100
|
+
rack (2.2.2)
|
101
101
|
rack-test (1.1.0)
|
102
102
|
rack (>= 1.0, < 3)
|
103
103
|
rails (6.0.2.1)
|
@@ -162,7 +162,7 @@ GEM
|
|
162
162
|
tins (~> 1.0)
|
163
163
|
thor (1.0.1)
|
164
164
|
thread_safe (0.3.6)
|
165
|
-
tins (1.24.
|
165
|
+
tins (1.24.1)
|
166
166
|
sync
|
167
167
|
tzinfo (1.2.6)
|
168
168
|
thread_safe (~> 0.1)
|
data/README.md
CHANGED
@@ -10,7 +10,7 @@
|
|
10
10
|
Web interface that allows you to manage easily your Redis instance (see keys, memory used, connected client, etc...).
|
11
11
|
|
12
12
|
### Check your stats
|
13
|
-
The Dashboard allows you
|
13
|
+
The Dashboard allows you to check the Memory usage, CPU and Redis clients.
|
14
14
|
|
15
15
|
![RedisWebManager Dashboard](images/images_dashboard.png)
|
16
16
|
|
@@ -103,7 +103,6 @@ end
|
|
103
103
|
|
104
104
|
|
105
105
|
## Todo
|
106
|
-
* [ ] Add filters to redis keys (filter by type, by expiration date...)
|
107
106
|
* [ ] Add graph for most used commands
|
108
107
|
* [ ] Manage multiple redis instances
|
109
108
|
* [ ] Real time chart update
|
@@ -10,15 +10,9 @@ module RedisWebManager
|
|
10
10
|
|
11
11
|
# GET /keys
|
12
12
|
def index
|
13
|
-
query = params[:query].presence
|
14
|
-
@keys = if query.present?
|
15
|
-
info.search(query).map { |key| format_key(key) }
|
16
|
-
else
|
17
|
-
info.keys.map { |key| format_key(key) }
|
18
|
-
end
|
19
13
|
@status = info.status
|
20
14
|
@url = connection.id
|
21
|
-
@pagy, @keys = pagy_array(
|
15
|
+
@pagy, @keys = pagy_array(keys)
|
22
16
|
end
|
23
17
|
|
24
18
|
# GET /key/:key
|
@@ -54,13 +48,14 @@ module RedisWebManager
|
|
54
48
|
|
55
49
|
private
|
56
50
|
|
51
|
+
# FIXME: - Refactoring
|
52
|
+
# - Move this part
|
57
53
|
def item_type(value)
|
58
54
|
['json', JSON.parse(value)]
|
59
55
|
rescue JSON::ParserError
|
60
56
|
['string', value]
|
61
57
|
end
|
62
58
|
|
63
|
-
# Get values for Redis List type
|
64
59
|
def get_list(key)
|
65
60
|
start = 0
|
66
61
|
stop = 99
|
@@ -74,7 +69,6 @@ module RedisWebManager
|
|
74
69
|
{ length: length, values: values }
|
75
70
|
end
|
76
71
|
|
77
|
-
# Get values for Redis Set type
|
78
72
|
def get_set(key)
|
79
73
|
values = info.smembers(key).map do |e|
|
80
74
|
type, value = item_type(e)
|
@@ -84,7 +78,6 @@ module RedisWebManager
|
|
84
78
|
{ values: values }
|
85
79
|
end
|
86
80
|
|
87
|
-
# Get values for Redis Zset type
|
88
81
|
def get_zset(key)
|
89
82
|
values = info.zrange(key, 0, -1, withscores: true).map do |e, score|
|
90
83
|
type, value = item_type(e)
|
@@ -94,7 +87,6 @@ module RedisWebManager
|
|
94
87
|
{ values: values }
|
95
88
|
end
|
96
89
|
|
97
|
-
# Get values for Redis Hash type
|
98
90
|
def get_hash(key)
|
99
91
|
value = Hash[info.hgetall(key).map do |k, v|
|
100
92
|
type, value = item_type(v)
|
@@ -105,8 +97,7 @@ module RedisWebManager
|
|
105
97
|
end
|
106
98
|
|
107
99
|
def get_value(key)
|
108
|
-
|
109
|
-
case type
|
100
|
+
case info.type(key)
|
110
101
|
when 'string'
|
111
102
|
{ value: info.get(key) }
|
112
103
|
when 'list'
|
@@ -125,11 +116,39 @@ module RedisWebManager
|
|
125
116
|
def format_key(key)
|
126
117
|
{
|
127
118
|
key: key,
|
128
|
-
|
119
|
+
expiry: info.expiry(key),
|
129
120
|
node: get_value(key),
|
130
121
|
type: info.type(key),
|
131
122
|
memory: info.memory_usage(key)
|
132
123
|
}
|
133
124
|
end
|
125
|
+
|
126
|
+
def keys
|
127
|
+
keys = info.search(params[:query].presence).map { |key| format_key(key) }
|
128
|
+
keys = filter_by_type(keys, params[:type].presence)
|
129
|
+
keys = filter_by_expiry(keys, params[:expiry].presence)
|
130
|
+
filter_by_memory(keys, params[:expiry].presence)
|
131
|
+
end
|
132
|
+
|
133
|
+
def filter_by_type(keys, type)
|
134
|
+
return keys if invalid_option(type)
|
135
|
+
keys.select { |key| key[:type] == type }
|
136
|
+
end
|
137
|
+
|
138
|
+
def filter_by_expiry(keys, expiry)
|
139
|
+
return keys if invalid_option(expiry)
|
140
|
+
duration = expiry.to_i
|
141
|
+
return keys.select { |key| key[:expiry] == -1 } if duration == -1
|
142
|
+
keys.select { |key| key[:expiry] != -1 && key[:expiry] < duration }
|
143
|
+
end
|
144
|
+
|
145
|
+
def filter_by_memory(keys, memory)
|
146
|
+
return keys if invalid_option(memory)
|
147
|
+
keys.select { |key| key[:memory] < memory.to_i }
|
148
|
+
end
|
149
|
+
|
150
|
+
def invalid_option(option)
|
151
|
+
option.nil? || option == 'all'
|
152
|
+
end
|
134
153
|
end
|
135
154
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RedisWebManager
|
4
|
+
module KeysHelper
|
5
|
+
def types_filters
|
6
|
+
[%w[All all],
|
7
|
+
%w[String string],
|
8
|
+
%w[Hash hash],
|
9
|
+
%w[Set set],
|
10
|
+
%w[Zset zset],
|
11
|
+
%w[List list]]
|
12
|
+
end
|
13
|
+
|
14
|
+
def expiry_filters
|
15
|
+
[%w[All all],
|
16
|
+
['No expiry', -1],
|
17
|
+
['Less than 1 hour', 3600],
|
18
|
+
['Less than 1 week', 604_800],
|
19
|
+
['Less than 1 month', 2_592_000],
|
20
|
+
['Less than 6 months', 15_552_000]]
|
21
|
+
end
|
22
|
+
|
23
|
+
def memory_filters
|
24
|
+
[%w[All all],
|
25
|
+
['Less than 1 KB', 1000],
|
26
|
+
['Less than 10 KB', 10_000],
|
27
|
+
['Less than 100 KB', 100_000],
|
28
|
+
['Less than 1 MB', 1_000_000],
|
29
|
+
['Less than 10 MB', 10_000_000],
|
30
|
+
['Less than 100 MB', 100_000_000]]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
<%= form_tag(keys_path, method: :get, class: 'p-4', enforce_utf8: false) do %>
|
2
|
+
<div class="row">
|
3
|
+
<div class="col-12">
|
4
|
+
<div class="form-group">
|
5
|
+
<%= label_tag :query, 'Name', class: 'font-weight-bolder' %>
|
6
|
+
<%= text_field_tag :query, params[:query], class: 'form-control', placeholder: 'Search key(s)' %>
|
7
|
+
</div>
|
8
|
+
</div>
|
9
|
+
</div>
|
10
|
+
<div class="row">
|
11
|
+
<div class="col-4">
|
12
|
+
<div class="form-group">
|
13
|
+
<%= label_tag :type, 'Type', class: 'font-weight-bolder' %>
|
14
|
+
<%= select_tag :type, options_for_select(types_filters, params[:type]), class: 'form-control custom-select' %>
|
15
|
+
</div>
|
16
|
+
</div>
|
17
|
+
<div class="col-4">
|
18
|
+
<div class="form-group">
|
19
|
+
<%= label_tag :expiry, 'Expiry', class: 'font-weight-bolder' %>
|
20
|
+
<%= select_tag :expiry, options_for_select(expiry_filters, params[:expiry]), class: 'form-control custom-select' %>
|
21
|
+
</div>
|
22
|
+
</div>
|
23
|
+
<div class="col-4">
|
24
|
+
<div class="form-group">
|
25
|
+
<%= label_tag :memory, 'Memory', class: 'font-weight-bolder' %>
|
26
|
+
<%= select_tag :memory, options_for_select(memory_filters, params[:memory]), class: 'form-control custom-select' %>
|
27
|
+
</div>
|
28
|
+
</div>
|
29
|
+
</div>
|
30
|
+
<%= submit_tag 'Search', class: 'btn btn-primary btn-block', name: nil %>
|
31
|
+
<% end %>
|
@@ -9,14 +9,12 @@
|
|
9
9
|
</h5>
|
10
10
|
</div>
|
11
11
|
<div class="card-body p-0">
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
</div>
|
19
|
-
<% end %>
|
12
|
+
<a class="btn btn-link p-2" data-toggle="collapse" href="#search" role="button" aria-expanded="false" aria-controls="search">
|
13
|
+
View search
|
14
|
+
</a>
|
15
|
+
<div class="collapse" id="search">
|
16
|
+
<%= render partial: 'redis_web_manager/keys/search' %>
|
17
|
+
</div>
|
20
18
|
<div class="table-responsive">
|
21
19
|
<table class="table mb-0">
|
22
20
|
<thead>
|
@@ -32,11 +30,11 @@
|
|
32
30
|
<% @keys.each do |key| %>
|
33
31
|
<tr>
|
34
32
|
<td><%= link_to (key[:key]).truncate(45), key_path(key: key[:key]), title: "Show #{key[:key]}" %></td>
|
35
|
-
<td><%=
|
33
|
+
<td><%= expiry(key[:expiry]) %></td>
|
36
34
|
<td><code><%= number_to_human_size(key[:memory]) %></code></td>
|
37
35
|
<td><kbd class="bg-dark"><%= key[:type] %></kbd></td>
|
38
36
|
<td>
|
39
|
-
<%= link_to 'Edit', edit_key_path(key: key[:key]), title: "Edit #{key[:key]}", class: 'btn btn-sm btn-primary
|
37
|
+
<%= link_to 'Edit', edit_key_path(key: key[:key]), title: "Edit #{key[:key]}", class: 'btn btn-sm btn-primary' %>
|
40
38
|
<%= link_to 'Delete', destroy_key_path(key: key[:key]), method: :delete, data: {confirm: 'Are you sure ?'}, title: "Delete #{key[:key]}", class: 'btn btn-sm btn-danger ml-2' %>
|
41
39
|
</td>
|
42
40
|
</tr>
|
@@ -10,19 +10,15 @@ module RedisWebManager
|
|
10
10
|
@stats ||= redis.info
|
11
11
|
end
|
12
12
|
|
13
|
-
def keys
|
14
|
-
@keys ||= redis.keys
|
15
|
-
end
|
16
|
-
|
17
13
|
def search(query)
|
18
|
-
redis.scan_each(match: "*#{query.downcase}*").to_a
|
14
|
+
redis.scan_each(match: "*#{query.try(:downcase)}*").to_a
|
19
15
|
end
|
20
16
|
|
21
17
|
def type(key)
|
22
18
|
redis.type(key)
|
23
19
|
end
|
24
20
|
|
25
|
-
def
|
21
|
+
def expiry(key)
|
26
22
|
redis.ttl(key)
|
27
23
|
end
|
28
24
|
|
@@ -12,7 +12,15 @@ RSpec.describe RedisWebManager::KeysController, type: :controller do
|
|
12
12
|
it 'returns a success response' do
|
13
13
|
get :index
|
14
14
|
expect(response).to be_successful
|
15
|
-
get :index, params: { query: '
|
15
|
+
get :index, params: { query: 'test' }
|
16
|
+
expect(response).to be_successful
|
17
|
+
get :index, params: { type: 'string' }
|
18
|
+
expect(response).to be_successful
|
19
|
+
get :index, params: { expiry: '-1' }
|
20
|
+
expect(response).to be_successful
|
21
|
+
get :index, params: { expiry: '3600' }
|
22
|
+
expect(response).to be_successful
|
23
|
+
get :index, params: { memory: '1000' }
|
16
24
|
expect(response).to be_successful
|
17
25
|
end
|
18
26
|
end
|
@@ -17,11 +17,11 @@ RSpec.describe RedisWebManager::ApplicationHelper, type: :helper do
|
|
17
17
|
end
|
18
18
|
|
19
19
|
it 'returns a no expiration' do
|
20
|
-
expect(helper.
|
20
|
+
expect(helper.expiry(-1)).to eql('No expiration date')
|
21
21
|
end
|
22
22
|
|
23
23
|
it 'returns a expiration' do
|
24
|
-
expect(helper.
|
24
|
+
expect(helper.expiry(86_400)).to eql('1 day')
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails_helper'
|
4
|
+
|
5
|
+
RSpec.describe RedisWebManager::KeysHelper, type: :helper do
|
6
|
+
describe 'helper' do
|
7
|
+
it 'returns Array of types' do
|
8
|
+
expect(helper.types_filters).to eql([%w[All all],
|
9
|
+
%w[String string],
|
10
|
+
%w[Hash hash],
|
11
|
+
%w[Set set],
|
12
|
+
%w[Zset zset],
|
13
|
+
%w[List list]])
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'returns Array of expiration' do
|
17
|
+
expect(helper.expiry_filters).to eq(
|
18
|
+
[%w[All all],
|
19
|
+
['No expiry', -1],
|
20
|
+
['Less than 1 hour', 3600],
|
21
|
+
['Less than 1 week', 604_800],
|
22
|
+
['Less than 1 month', 2_592_000],
|
23
|
+
['Less than 6 months', 15_552_000]]
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'returns Array of memories' do
|
28
|
+
expect(helper.memory_filters).to eq(
|
29
|
+
[%w[All all],
|
30
|
+
['Less than 1 KB', 1000],
|
31
|
+
['Less than 10 KB', 10_000],
|
32
|
+
['Less than 100 KB', 100_000],
|
33
|
+
['Less than 1 MB', 1_000_000],
|
34
|
+
['Less than 10 MB', 10_000_000],
|
35
|
+
['Less than 100 MB', 100_000_000]]
|
36
|
+
)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -20,9 +20,6 @@ RSpec.describe RedisWebManager::Info do
|
|
20
20
|
expect(info.stats).to be_a_kind_of(Hash)
|
21
21
|
end
|
22
22
|
|
23
|
-
it 'returns a Array class (keys)' do
|
24
|
-
expect(info.keys).to be_a_kind_of(Array)
|
25
|
-
end
|
26
23
|
|
27
24
|
it 'returns a string value (type)' do
|
28
25
|
redis.set('test', 'test', ex: 20.seconds)
|
@@ -35,7 +32,7 @@ RSpec.describe RedisWebManager::Info do
|
|
35
32
|
end
|
36
33
|
|
37
34
|
it 'returns a ttl value (expire)' do
|
38
|
-
expect(info.
|
35
|
+
expect(info.expiry('test')).to eql(20)
|
39
36
|
end
|
40
37
|
|
41
38
|
it 'returns a memory usage value (memory_usage)' do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis_web_manager
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Boris BRESCIANI
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: exe
|
12
12
|
cert_chain: []
|
13
|
-
date: 2020-02-
|
13
|
+
date: 2020-02-18 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: coveralls
|
@@ -143,11 +143,13 @@ files:
|
|
143
143
|
- app/helpers/redis_web_manager/application_helper.rb
|
144
144
|
- app/helpers/redis_web_manager/clients_helper.rb
|
145
145
|
- app/helpers/redis_web_manager/dashboard_helper.rb
|
146
|
+
- app/helpers/redis_web_manager/keys_helper.rb
|
146
147
|
- app/views/layouts/redis_web_manager/application.html.erb
|
147
148
|
- app/views/redis_web_manager/clients/index.html.erb
|
148
149
|
- app/views/redis_web_manager/configuration/index.html.erb
|
149
150
|
- app/views/redis_web_manager/dashboard/index.html.erb
|
150
151
|
- app/views/redis_web_manager/information/index.html.erb
|
152
|
+
- app/views/redis_web_manager/keys/_search.html.erb
|
151
153
|
- app/views/redis_web_manager/keys/edit.html.erb
|
152
154
|
- app/views/redis_web_manager/keys/index.html.erb
|
153
155
|
- app/views/redis_web_manager/keys/show.html.erb
|
@@ -343,6 +345,7 @@ files:
|
|
343
345
|
- spec/helpers/application_helper_spec.rb
|
344
346
|
- spec/helpers/clients_helper_spec.rb
|
345
347
|
- spec/helpers/dashboard_helper_spec.rb
|
348
|
+
- spec/helpers/keys_helper_spec.rb
|
346
349
|
- spec/rails_helper.rb
|
347
350
|
- spec/redis_web_manager_action_spec.rb
|
348
351
|
- spec/redis_web_manager_connection_spec.rb
|
@@ -570,3 +573,4 @@ test_files:
|
|
570
573
|
- spec/helpers/application_helper_spec.rb
|
571
574
|
- spec/helpers/clients_helper_spec.rb
|
572
575
|
- spec/helpers/dashboard_helper_spec.rb
|
576
|
+
- spec/helpers/keys_helper_spec.rb
|