redis_web_manager 0.1.6 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/.coveralls.yml +2 -0
  3. data/.travis.yml +1 -0
  4. data/Gemfile.lock +23 -1
  5. data/README.md +95 -4
  6. data/Rakefile +1 -1
  7. data/app/controllers/redis_web_manager/actions_controller.rb +15 -3
  8. data/app/controllers/redis_web_manager/application_controller.rb +4 -0
  9. data/app/controllers/redis_web_manager/clients_controller.rb +1 -1
  10. data/app/controllers/redis_web_manager/configuration_controller.rb +1 -1
  11. data/app/controllers/redis_web_manager/dashboard_controller.rb +23 -3
  12. data/app/controllers/redis_web_manager/information_controller.rb +1 -1
  13. data/app/controllers/redis_web_manager/keys_controller.rb +135 -0
  14. data/app/helpers/redis_web_manager/application_helper.rb +16 -0
  15. data/app/helpers/redis_web_manager/dashboard_helper.rb +1 -1
  16. data/app/views/redis_web_manager/dashboard/index.html.erb +20 -1
  17. data/app/views/redis_web_manager/keys/edit.html.erb +14 -0
  18. data/app/views/redis_web_manager/keys/index.html.erb +54 -0
  19. data/app/views/redis_web_manager/keys/show.html.erb +30 -0
  20. data/app/views/redis_web_manager/shared/_header.html.erb +12 -2
  21. data/app/views/redis_web_manager/shared/_status.html.erb +2 -2
  22. data/bin/rails +1 -1
  23. data/config/routes.rb +8 -0
  24. data/lib/redis_web_manager.rb +1 -1
  25. data/lib/redis_web_manager/action.rb +1 -1
  26. data/lib/redis_web_manager/data.rb +16 -0
  27. data/lib/redis_web_manager/version.rb +1 -1
  28. data/redis_web_manager.gemspec +6 -4
  29. data/spec/controllers/redis_web_manager/actions_controller_spec.rb +16 -1
  30. data/spec/controllers/redis_web_manager/clients_controller_spec.rb +1 -1
  31. data/spec/controllers/redis_web_manager/keys_controller_spec.rb +139 -0
  32. data/spec/helpers/application_helper_spec.rb +13 -1
  33. data/spec/helpers/dashboard_helper_spec.rb +1 -1
  34. data/spec/redis_web_manager_data_spec.rb +23 -0
  35. data/spec/routing/actions_controller_spec.rb +6 -0
  36. data/spec/routing/keys_controller_spec.rb +39 -0
  37. data/spec/spec_helper.rb +6 -0
  38. metadata +295 -342
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6a061b03c469a48d07ac3adf06ee448e86d36ad2a135103588e7ccbe181def86
4
- data.tar.gz: 5ae9e1e12c3a5700f8d10744a70008818915ddf4534e9cd3f472823de4f1d93a
3
+ metadata.gz: e48c79b5d3723da1e569b6ab98470b268a694b6f3d39a08666945a4349c09666
4
+ data.tar.gz: f92ce3f1270fdfbf2c41744aa0c6f6c210dc4bd015ed44b645e924d814ffc3f8
5
5
  SHA512:
6
- metadata.gz: 04fe5ddf7a965b48333dd9da4ebc9b3fb1e0c4077d071cca9aa6629063ebdb5982363f383fc9151ef4f05c7cd52b02c2fc6863d366ffbfefda0d0db2c3198b64
7
- data.tar.gz: ee93576a04f0e09290d6fbc17569a34f496e363023722b153e73e755e9871d6909a87a589935c5ac895c586cc4395ab43e187c7ccb27b9094a712db4f8fd9cc5
6
+ metadata.gz: d2246f99e9a53f9bc9cec38b06e95b967250cbab37104544f80f058d06402c6130d7d1f010e7b52cd71428a8c7d45a7d1c806f6628a372a368929119b4d7c8d4
7
+ data.tar.gz: eac5fb2aea1185697a9ae819b06817b206db4adba61371462a182e5ab3ccf5d9430ddb4a03de80f1045bd4a7d33fa605d7958e07311146f605c4052644bab538
@@ -0,0 +1,2 @@
1
+ service_name: travis-pro
2
+ repo_token: A7Nr6g7XhQgiadtP7z5SZjlMYWVTFt0rx
@@ -7,6 +7,7 @@ services:
7
7
  rvm:
8
8
  - 2.5.5
9
9
  - 2.6.3
10
+ - 2.7.0
10
11
  gemfile:
11
12
  - gemfiles/Gemfile-5-2
12
13
  - gemfiles/Gemfile-6-0
@@ -1,7 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- redis_web_manager (0.1.5)
4
+ redis_web_manager (0.1.6)
5
+ pagy (~> 3.7)
5
6
  rails (>= 5.2, < 7)
6
7
  redis (~> 4.1.0)
7
8
 
@@ -65,13 +66,21 @@ GEM
65
66
  zeitwerk (~> 2.2)
66
67
  builder (3.2.4)
67
68
  concurrent-ruby (1.1.5)
69
+ coveralls (0.8.23)
70
+ json (>= 1.8, < 3)
71
+ simplecov (~> 0.16.1)
72
+ term-ansicolor (~> 1.3)
73
+ thor (>= 0.19.4, < 2.0)
74
+ tins (~> 1.6)
68
75
  crass (1.0.6)
69
76
  diff-lcs (1.3)
77
+ docile (1.3.2)
70
78
  erubi (1.9.0)
71
79
  globalid (0.4.2)
72
80
  activesupport (>= 4.2.0)
73
81
  i18n (1.8.2)
74
82
  concurrent-ruby (~> 1.0)
83
+ json (2.3.0)
75
84
  loofah (2.4.0)
76
85
  crass (~> 1.0.2)
77
86
  nokogiri (>= 1.5.9)
@@ -87,6 +96,7 @@ GEM
87
96
  nio4r (2.5.2)
88
97
  nokogiri (1.10.7)
89
98
  mini_portile2 (~> 2.4.0)
99
+ pagy (3.7.2)
90
100
  rack (2.1.2)
91
101
  rack-test (1.1.0)
92
102
  rack (>= 1.0, < 3)
@@ -135,6 +145,11 @@ GEM
135
145
  rspec-mocks (~> 3.8)
136
146
  rspec-support (~> 3.8)
137
147
  rspec-support (3.9.2)
148
+ simplecov (0.16.1)
149
+ docile (~> 1.1)
150
+ json (>= 1.8, < 3)
151
+ simplecov-html (~> 0.10.0)
152
+ simplecov-html (0.10.2)
138
153
  sprockets (4.0.0)
139
154
  concurrent-ruby (~> 1.0)
140
155
  rack (> 1, < 3)
@@ -142,8 +157,13 @@ GEM
142
157
  actionpack (>= 4.0)
143
158
  activesupport (>= 4.0)
144
159
  sprockets (>= 3.0.0)
160
+ sync (0.5.0)
161
+ term-ansicolor (1.7.1)
162
+ tins (~> 1.0)
145
163
  thor (1.0.1)
146
164
  thread_safe (0.3.6)
165
+ tins (1.24.0)
166
+ sync
147
167
  tzinfo (1.2.6)
148
168
  thread_safe (~> 0.1)
149
169
  websocket-driver (0.7.1)
@@ -155,8 +175,10 @@ PLATFORMS
155
175
  ruby
156
176
 
157
177
  DEPENDENCIES
178
+ coveralls (~> 0.8)
158
179
  redis_web_manager!
159
180
  rspec-rails (= 4.0.0.beta3)
181
+ simplecov (~> 0.16)
160
182
 
161
183
  BUNDLED WITH
162
184
  2.1.4
data/README.md CHANGED
@@ -1,9 +1,28 @@
1
1
  # RedisWebManager
2
2
 
3
- Short description and motivation.
3
+ [![Gem Version](https://badge.fury.io/rb/redis_web_manager.svg)](https://badge.fury.io/rb/redis_web_manager)
4
+ [![Maintainability](https://api.codeclimate.com/v1/badges/55600fe789679fe62d8b/maintainability)](https://codeclimate.com/github/OpenGems/redis_web_manager/maintainability)
5
+ [![Build Status](https://travis-ci.org/OpenGems/redis_web_manager.svg?branch=master)](https://travis-ci.org/OpenGems/redis_web_manager)
6
+ [![security](https://hakiri.io/github/OpenGems/redis_web_manager/master.svg)](https://hakiri.io/github/OpenGems/redis_web_manager/master)
7
+ ![Gem](https://img.shields.io/gem/dt/redis_web_manager)
8
+ [![Coverage Status](https://coveralls.io/repos/github/OpenGems/redis_web_manager/badge.svg?branch=master)](https://coveralls.io/github/OpenGems/redis_web_manager?branch=master)
4
9
 
5
- ## Usage
6
- How to use my plugin.
10
+ Web interface that allows you to manage easily your Redis instance (see keys, memory used, connected client, etc...).
11
+
12
+ ### Check your stats
13
+ The Dashboard allows you tu check the Memory usage, CPU and Redis clients.
14
+
15
+ ![RedisWebManager Dashboard](images/images_dashboard.png)
16
+
17
+ ### Manage your redis keys
18
+ You can easily edit and delete any keys stored in your redis database.
19
+
20
+ ![RedisWebManager Keys](images/images_keys.png)
21
+
22
+ ### Keep an eye on your redis clients
23
+ Check how many clients are connected and their infos.
24
+
25
+ ![RedisWebManager Clients](images/images_clients.png)
7
26
 
8
27
  ## Installation
9
28
  Add this line to your application's Gemfile:
@@ -22,8 +41,80 @@ Or install it yourself as:
22
41
  $ gem install redis_web_manager
23
42
  ```
24
43
 
44
+ Add the custom route in your `routes.rb`:
45
+ ```
46
+ mount RedisWebManager::Engine => '/redis_web_manager'
47
+ ```
48
+
49
+ Access to RedisWebManager at `/redis_web_manager`
50
+
51
+ ## Configuration
52
+
53
+ You can configure RedisWebManager:
54
+
55
+ ```ruby
56
+ # initializers/redis_web_manager.rb
57
+
58
+ RedisWebManager.configure do |config|
59
+ config.redis = Redis.new(db: 1) # Default Redis.new (Instance of Redis)
60
+ config.lifespan = 2.days # Default 15.days (Lifespan of each keys for dashboard)
61
+ config.authenticate = proc {
62
+ authenticate_or_request_with_http_basic do |username, password|
63
+ username == 'TEST' && password == 'TEST'
64
+ end
65
+ } # Default nil (Authenticate method to secure tools)
66
+ end
67
+ ```
68
+
69
+ ## Collect data for dashboard
70
+
71
+ In order to have data on your dashboard you must collect the data like this:
72
+ ```ruby
73
+ data = RedisWebManager::Data.new
74
+ data.perform
75
+ ```
76
+
77
+ If you are using a system to run background tasks in your application (like Sidekiq, Sucker Punch or ActiveJob), you can write your own background task to update the dashboard statistics.
78
+
79
+ Sidekiq exemple:
80
+ ```ruby
81
+ class DashboardWorker
82
+ include Sidekiq::Worker
83
+
84
+ def perform
85
+ data = RedisWebManager::Data.new
86
+ data.perform
87
+ end
88
+ end
89
+ ```
90
+
91
+ Sucker Punch exemple:
92
+ ```ruby
93
+ class DashboardJob
94
+ include SuckerPunch::Job
95
+
96
+ def perform
97
+ data = RedisWebManager::Data.new
98
+ data.perform
99
+ end
100
+ end
101
+ ```
102
+
103
+
104
+
105
+ ## Todo
106
+ * [ ] Add filters to redis keys (filter by type, by expiration date...)
107
+ * [ ] Add graph for most used commands
108
+ * [ ] Manage multiple redis instances
109
+ * [ ] Real time chart update
110
+ * [ ] Alert system (ex: triggered when memory is peaking)
111
+ * [ ] Command line interface to manage your redis database
112
+ * [ ] Logs interface
113
+
114
+
25
115
  ## Contributing
26
- Contribution directions go here.
116
+ Bug reports and pull requests are welcome on GitHub at https://github.com/OpenGems/redis_web_manager. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
27
117
 
28
118
  ## License
119
+
29
120
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile CHANGED
@@ -25,4 +25,4 @@ require 'rspec/core/rake_task'
25
25
 
26
26
  RSpec::Core::RakeTask.new(:spec)
27
27
 
28
- task default: :spec
28
+ task default: :spec
@@ -2,10 +2,22 @@
2
2
 
3
3
  module RedisWebManager
4
4
  class ActionsController < ApplicationController
5
+ # DELETE /reset
6
+ def reset
7
+ data.flush
8
+ redirect_to root_url
9
+ end
10
+
5
11
  # DELETE /flushdb
6
- def flushdb; end
12
+ def flushdb
13
+ action.flushdb
14
+ redirect_to root_url
15
+ end
7
16
 
8
17
  # DELETE /flushall
9
- def flushall; end
18
+ def flushall
19
+ action.flushall
20
+ redirect_to root_url
21
+ end
10
22
  end
11
- end
23
+ end
@@ -27,5 +27,9 @@ module RedisWebManager
27
27
  def action
28
28
  @action ||= RedisWebManager::Action.new
29
29
  end
30
+
31
+ def data
32
+ @data ||= RedisWebManager::Data.new
33
+ end
30
34
  end
31
35
  end
@@ -9,4 +9,4 @@ module RedisWebManager
9
9
  @clients = info.clients.map(&:symbolize_keys)
10
10
  end
11
11
  end
12
- end
12
+ end
@@ -9,4 +9,4 @@ module RedisWebManager
9
9
  @url = connection.id
10
10
  end
11
11
  end
12
- end
12
+ end
@@ -4,11 +4,31 @@ module RedisWebManager
4
4
  class DashboardController < ApplicationController
5
5
  # GET /dashboard
6
6
  def index
7
+ @information = stats.map { |k, v| { name: k.to_s.humanize, value: v } }
7
8
  @status = info.status
8
9
  @url = connection.id
9
- @memory = []
10
- @cpu = []
11
- @client = []
10
+ @memory = keys_by_type(data.keys, :memory)
11
+ @cpu = keys_by_type(data.keys, :cpu)
12
+ @client = keys_by_type(data.keys, :client)
13
+ end
14
+
15
+ private
16
+
17
+ def stats
18
+ @stats ||= info.stats.symbolize_keys.slice(:redis_version,
19
+ :redis_mode,
20
+ :arch_bits,
21
+ :process_id,
22
+ :os,
23
+ :role,
24
+ :connected_clients,
25
+ :blocked_clients,
26
+ :uptime_in_days,
27
+ :used_memory_human)
28
+ end
29
+
30
+ def keys_by_type(keys, value)
31
+ keys.map { |key| key.slice(:date, value) }.sort_by { |key| key[:date] }
12
32
  end
13
33
  end
14
34
  end
@@ -15,4 +15,4 @@ module RedisWebManager
15
15
  @stats ||= info.stats.symbolize_keys
16
16
  end
17
17
  end
18
- end
18
+ end
@@ -0,0 +1,135 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pagy'
4
+ require 'pagy/extras/array'
5
+ require 'pagy/extras/bootstrap'
6
+
7
+ module RedisWebManager
8
+ class KeysController < ApplicationController
9
+ include ::Pagy::Backend
10
+
11
+ # GET /keys
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
+ @status = info.status
20
+ @url = connection.id
21
+ @pagy, @keys = pagy_array(@keys)
22
+ end
23
+
24
+ # GET /key/:key
25
+ def show
26
+ key = params[:key].presence
27
+ redirect_to keys_url if key.nil?
28
+ @key = format_key(key)
29
+ end
30
+
31
+ # GET /key/:key
32
+ def edit
33
+ key = params[:key].presence
34
+ redirect_to keys_url if key.nil?
35
+ @key = format_key(key)
36
+ end
37
+
38
+ # PUT /key/:key
39
+ def update
40
+ old_key = params[:old_name].presence
41
+ new_name = params[:new_name].presence
42
+ redirect_to keys_url if old_key.nil? || new_name.nil?
43
+ action.rename(old_key, new_name)
44
+ redirect_to keys_url
45
+ end
46
+
47
+ # DELETE /key/:key
48
+ def destroy
49
+ key = params[:key].presence
50
+ redirect_to keys_url if key.nil?
51
+ action.del(key)
52
+ redirect_to keys_url
53
+ end
54
+
55
+ private
56
+
57
+ def item_type(value)
58
+ ['json', JSON.parse(value)]
59
+ rescue JSON::ParserError
60
+ ['string', value]
61
+ end
62
+
63
+ # Get values for Redis List type
64
+ def get_list(key)
65
+ start = 0
66
+ stop = 99
67
+
68
+ length = info.llen(key)
69
+ values = info.lrange(key, start, stop).map.with_index do |e, i|
70
+ type, value = item_type(e)
71
+ { type: type, value: value, index: start + i }
72
+ end
73
+
74
+ { length: length, values: values }
75
+ end
76
+
77
+ # Get values for Redis Set type
78
+ def get_set(key)
79
+ values = info.smembers(key).map do |e|
80
+ type, value = item_type(e)
81
+ { type: type, value: value }
82
+ end
83
+
84
+ { values: values }
85
+ end
86
+
87
+ # Get values for Redis Zset type
88
+ def get_zset(key)
89
+ values = info.zrange(key, 0, -1, withscores: true).map do |e, score|
90
+ type, value = item_type(e)
91
+ { type: type, value: value, score: score }
92
+ end
93
+
94
+ { values: values }
95
+ end
96
+
97
+ # Get values for Redis Hash type
98
+ def get_hash(key)
99
+ value = Hash[info.hgetall(key).map do |k, v|
100
+ type, value = item_type(v)
101
+ [k, { type: type, value: value }]
102
+ end]
103
+
104
+ { value: value }
105
+ end
106
+
107
+ def get_value(key)
108
+ type = info.type(key)
109
+ case type
110
+ when 'string'
111
+ { value: info.get(key) }
112
+ when 'list'
113
+ get_list(key)
114
+ when 'set'
115
+ get_set(key)
116
+ when 'zset'
117
+ get_zset(key)
118
+ when 'hash'
119
+ get_hash(key)
120
+ else
121
+ { value: 'Not found' }
122
+ end
123
+ end
124
+
125
+ def format_key(key)
126
+ {
127
+ key: key,
128
+ expire: info.expire(key),
129
+ node: get_value(key),
130
+ type: info.type(key),
131
+ memory: info.memory_usage(key)
132
+ }
133
+ end
134
+ end
135
+ end