redis_web_manager 0.1.6 → 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
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