amnesia 1.0.0 → 1.1.0
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.
- checksums.yaml +7 -0
- data/README.markdown +51 -6
- data/lib/amnesia/authentication.rb +12 -0
- data/lib/amnesia/helpers.rb +44 -0
- data/lib/amnesia/host.rb +63 -27
- data/lib/amnesia/public/css/application.css +75 -27
- data/lib/amnesia/routes.rb +41 -0
- data/lib/amnesia/views/host.haml +29 -21
- data/lib/amnesia/views/index.haml +28 -23
- data/lib/amnesia/views/layout.haml +9 -9
- data/lib/amnesia.rb +17 -45
- metadata +91 -105
- data/lib/core_ext/array.rb +0 -5
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 38e6536f54a144f1ca9cfbbf47725f278176cb392ec7a3c7e6e8e1782631a9ce
|
4
|
+
data.tar.gz: f4d82c911b950cabfbd87d93e79df8d53a4d7fe938089a7416a331ff2544b22d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5c4e0420c9dc06c9a5133b43ab5a8dee2b9557f5985970955a85e3e2d33da8752d25dc9b73819283abc0c82a72cb9b57d78e89bba67db6737202d786ef68192f
|
7
|
+
data.tar.gz: e05dbdfda49c7ba87c088fd63516c485b7e8271d3953b18951f83320d3c7e6b6b54faffef1f3d0c5206b26e11de6b3913e8f6018f18350a7a1f85a6e198dd382
|
data/README.markdown
CHANGED
@@ -8,7 +8,7 @@ Hopefully with Amnesia you'll know exactly whats happening with memory when it c
|
|
8
8
|
|
9
9
|
## Why?
|
10
10
|
|
11
|
-
Its always nice to have some statistics to see how everything is performing within your stack. Memcached seems to be a mystery box that people don't really pay
|
11
|
+
Its always nice to have some statistics to see how everything is performing within your stack. Memcached seems to be a mystery box that people don't really pay a lot of attention to.
|
12
12
|
|
13
13
|
Amnesia tells you how your application is performing, when it misses, when it is running sweet, when you're about to run out of memcached and (perhaps) fall down in a screaming heap.
|
14
14
|
|
@@ -16,7 +16,7 @@ Amnesia tells you how your application is performing, when it misses, when it is
|
|
16
16
|
|
17
17
|
All stats are since each memcached instance was restarted
|
18
18
|
|
19
|
-
Available as a
|
19
|
+
Available as a cumulative result of all your memcached instances, or single instances alone:
|
20
20
|
|
21
21
|
* Cache hits and misses
|
22
22
|
* Reads and writes
|
@@ -35,16 +35,61 @@ Available for single instances only:
|
|
35
35
|
|
36
36
|
gem install amnesia
|
37
37
|
|
38
|
-
### How to run it alongside your application
|
38
|
+
### How to run it alongside your Rack application
|
39
39
|
|
40
40
|
"config.ru":
|
41
41
|
|
42
42
|
require 'amnesia'
|
43
|
-
|
44
|
-
|
43
|
+
rack_app = Rack::Builder.app do
|
44
|
+
map "/amnesia" do
|
45
|
+
run Amnesia::Application.new
|
46
|
+
end
|
47
|
+
run YourSinatra::Application
|
48
|
+
end
|
49
|
+
run rack_app
|
50
|
+
|
51
|
+
### How to run it alongside your Rails application
|
52
|
+
|
53
|
+
"Gemfile":
|
54
|
+
|
55
|
+
gem 'amnesia', '>=1.0.2'
|
56
|
+
|
57
|
+
|
58
|
+
"config/routes.rb":
|
59
|
+
|
60
|
+
mount Amnesia::Application.new => "/amnesia"
|
61
|
+
|
45
62
|
|
46
63
|
### Then, cruise on over to `your-host.tld/amnesia`
|
47
64
|
|
65
|
+
|
66
|
+
## Configuration options
|
67
|
+
|
68
|
+
### Hosts
|
69
|
+
Amnesia will work automagically if you drop it on a Heroku powered app, likewise—for a "standard" memcache host (running on localhost:11211, the default.).
|
70
|
+
|
71
|
+
When you need to specify where your memcache hosts can be found, you can either set an environment variable:
|
72
|
+
|
73
|
+
ENV["MEMCACHE_SERVERS"] = ['localhost:11211']
|
74
|
+
|
75
|
+
or alternately, you can set it within your `config.ru`:
|
76
|
+
|
77
|
+
use Amnesia::Application, hosts: ["mc1.yourapp.com:11211", "mc2.yourapp.com:11211"]
|
78
|
+
|
79
|
+
### Authentication
|
80
|
+
|
81
|
+
When you want to keep your Amnesia data private, you can set an environment variable that will enable http basic authentication:
|
82
|
+
|
83
|
+
ENV["AMNESIA_CREDS"] = ben:schwarz
|
84
|
+
|
85
|
+
in your shell, you might do it like this:
|
86
|
+
|
87
|
+
export AMNESIA_CREDS=ben:schwarz
|
88
|
+
|
89
|
+
on heroku, like this:
|
90
|
+
|
91
|
+
heroku config:add AMNESIA_CREDS=ben:schwarz
|
92
|
+
|
48
93
|
## Potential issues
|
49
94
|
|
50
95
|
* Hosts are listed as "Inactive" or "Not Responding"
|
@@ -58,7 +103,7 @@ Within my slices, I punched a hole through `iptables`
|
|
58
103
|
|
59
104
|
You won't need to do this unless you've explicitly blocked ports to your server. (When in doubt, block nearly everything)
|
60
105
|
|
61
|
-
Let me know if you come
|
106
|
+
Let me know if you come across any issues using Github messaging.
|
62
107
|
|
63
108
|
## Something missing?
|
64
109
|
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Amnesia
|
2
|
+
module Authentication
|
3
|
+
def self.included app
|
4
|
+
app.class_eval do
|
5
|
+
use Rack::Auth::Basic, "Amnesia" do |username, password|
|
6
|
+
user, pass = ENV['AMNESIA_CREDS'].split(':')
|
7
|
+
username == user and password == pass
|
8
|
+
end if ENV['AMNESIA_CREDS']
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Amnesia
|
2
|
+
module Helpers
|
3
|
+
def self.included app
|
4
|
+
app.helpers do
|
5
|
+
include HelperMethods
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
module HelperMethods
|
10
|
+
SIZE_UNITS = %w[ Bytes KB MB GB TB PB EB ]
|
11
|
+
|
12
|
+
def graph_url(*data)
|
13
|
+
url "/pie?d="+data.join(',')
|
14
|
+
end
|
15
|
+
|
16
|
+
# https://github.com/rails/rails/blob/fbe335cfe09bf0949edfdf0c4b251f4d081bd5d7/activesupport/lib/active_support/number_helper/number_to_human_size_converter.rb
|
17
|
+
def number_to_human_size(number, precision=1)
|
18
|
+
number, base = Float(number), 1024
|
19
|
+
|
20
|
+
if number.to_i < base
|
21
|
+
"%d %s" % [ number.to_i, SIZE_UNITS.first ]
|
22
|
+
else
|
23
|
+
max = SIZE_UNITS.size - 1
|
24
|
+
exp = (Math.log(number) / Math.log(base)).to_i
|
25
|
+
exp = max if exp > max # avoid overflow for the highest unit
|
26
|
+
result = number / (base**exp)
|
27
|
+
"%.#{precision}f %s" % [ result, SIZE_UNITS[exp] ]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def alive_hosts
|
32
|
+
@alive_hosts ||= @hosts.select(&:alive?)
|
33
|
+
end
|
34
|
+
|
35
|
+
%w[ bytes limit_maxbytes get_hits get_misses cmd_get cmd_set ].each do |stat|
|
36
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
37
|
+
def #{stat}_sum
|
38
|
+
alive_hosts.map(&:#{stat}).sum
|
39
|
+
end
|
40
|
+
RUBY
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/amnesia/host.rb
CHANGED
@@ -1,29 +1,65 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
1
|
+
require 'dalli'
|
2
|
+
|
3
|
+
module Amnesia
|
4
|
+
class Host
|
5
|
+
FLOAT_STATS = %w[ rusage_user rusage_system ]
|
6
|
+
STRING_STATS = %w[ version libevent ]
|
7
|
+
DEFAULT_PORT = 11_211
|
8
|
+
|
9
|
+
def self.normalize_address address
|
10
|
+
return "#{address}:#{DEFAULT_PORT}" unless address.include? ":"
|
11
|
+
|
12
|
+
address
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(address)
|
16
|
+
@address = self.class.normalize_address address
|
17
|
+
end
|
18
|
+
|
19
|
+
def alive?
|
20
|
+
return true if connection.stats[@address]
|
21
|
+
rescue Dalli::DalliError
|
22
|
+
return false
|
23
|
+
end
|
24
|
+
|
25
|
+
def method_missing(method, *args)
|
26
|
+
if stats.has_key? method.to_s
|
27
|
+
value = stats[method.to_s]
|
28
|
+
if FLOAT_STATS.include? method
|
29
|
+
Float(value)
|
30
|
+
elsif STRING_STATS.include? method
|
31
|
+
value
|
32
|
+
else
|
33
|
+
Integer(value)
|
34
|
+
end
|
35
|
+
else
|
36
|
+
super
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def stats
|
41
|
+
stats_val = connection.stats
|
42
|
+
stats_val.values.first || {}
|
43
|
+
end
|
44
|
+
|
45
|
+
def address
|
46
|
+
@address || @connection.servers.join(', ')
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def connection
|
52
|
+
@connection ||= connect(@address)
|
53
|
+
end
|
54
|
+
|
55
|
+
def connect(address = nil)
|
56
|
+
if defined?(EM) && EM.respond_to?(:reactor_running?) && EM::reactor_running?
|
57
|
+
opts = {async: true}
|
58
|
+
else
|
59
|
+
opts = {}
|
60
|
+
end
|
61
|
+
Dalli::Client.new(address, opts)
|
62
|
+
end
|
63
|
+
|
28
64
|
end
|
29
65
|
end
|
@@ -1,38 +1,86 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
body, h1, h2, h3, h4, h5, h6, p, a, ul, ol, dl, dt, dd, table, caption, th, td,
|
2
|
+
fieldset, legend, blockquote {
|
3
|
+
font-weight: normal;
|
4
|
+
margin: 0;
|
5
|
+
padding: 0;
|
6
|
+
color: inherit;
|
7
|
+
list-style-type: none;
|
8
|
+
}
|
9
|
+
a img, form, legend {border: 0; }
|
3
10
|
|
4
|
-
|
5
|
-
body, h1, h2, h3, h4, h5, h6, p, a, ul, ol, dl, dt, dd, table, caption, th, td, fieldset, legend, blockquote { font-weight: normal; margin: 0; padding: 0; color: inherit; list-style-type: none; }
|
6
|
-
a img, form, legend { border: 0; }
|
11
|
+
html { color: #454545;}
|
7
12
|
|
8
|
-
|
9
|
-
|
13
|
+
body {
|
14
|
+
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
15
|
+
margin: 0 auto;
|
16
|
+
padding: 0 1em;
|
17
|
+
max-width: 450px;
|
18
|
+
text-rendering: optimizeLegibility;
|
19
|
+
-webkit-font-smoothing: antialiased;
|
20
|
+
}
|
10
21
|
|
11
|
-
h1, h2, h3 { color: #1f1f1f; }
|
12
22
|
img { display: block; }
|
13
|
-
a { color:
|
23
|
+
a:hover { color: #000; }
|
14
24
|
|
15
25
|
header { margin: 1em 0; }
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
header p { font-size: 0.8em; color: #454545; }
|
26
|
+
.brand { font-size: 3.5em; }
|
27
|
+
.brand a { display: block; text-decoration: none; }
|
28
|
+
.brand a:hover:after { content: "—Huh?";}
|
20
29
|
|
21
|
-
|
22
|
-
|
30
|
+
.host {
|
31
|
+
font-size: 1em;
|
32
|
+
color: #fff;
|
33
|
+
}
|
34
|
+
.host-address {
|
35
|
+
font-weight: bold;
|
36
|
+
color: #ff9900;
|
37
|
+
border-radius: 2px;
|
38
|
+
font-size: 0.9em;
|
39
|
+
}
|
40
|
+
.host-details {
|
41
|
+
color: #000;
|
42
|
+
padding: 2px 4px;
|
43
|
+
}
|
23
44
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
45
|
+
.stats {
|
46
|
+
display: flex;
|
47
|
+
align-items: center;
|
48
|
+
margin: 2em 0;
|
49
|
+
}
|
50
|
+
.stats-text {
|
51
|
+
flex: 1 1;
|
52
|
+
margin-left: 1.5em;
|
53
|
+
}
|
29
54
|
|
30
|
-
|
55
|
+
.graph-indicator { color: #ff9900; }
|
31
56
|
|
32
|
-
|
33
|
-
|
34
|
-
|
57
|
+
.alive-host,
|
58
|
+
.dead-host {
|
59
|
+
margin: 0.5em 0;
|
60
|
+
}
|
61
|
+
.dead-host { color: #999; }
|
35
62
|
|
36
|
-
footer {
|
37
|
-
|
38
|
-
|
63
|
+
footer {
|
64
|
+
margin-top: 2em;
|
65
|
+
border-top: 0.1em solid #ccc;
|
66
|
+
margin: 2em auto;
|
67
|
+
padding: 0.5em 0;
|
68
|
+
font-size: 0.8em;
|
69
|
+
color: #ccc;
|
70
|
+
text-align: center;
|
71
|
+
}
|
72
|
+
footer a:hover { color: #999; }
|
73
|
+
|
74
|
+
@media (prefers-color-scheme: dark) {
|
75
|
+
html {
|
76
|
+
background: black;
|
77
|
+
color: white;
|
78
|
+
color: #ccc;
|
79
|
+
}
|
80
|
+
a:hover { color: #fff; }
|
81
|
+
footer { border-color: #454545; color: #454545; }
|
82
|
+
.host-details {
|
83
|
+
color: #fff;
|
84
|
+
}
|
85
|
+
|
86
|
+
}
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Amnesia
|
2
|
+
module Routes
|
3
|
+
def self.included app
|
4
|
+
app.class_eval do
|
5
|
+
get '/' do
|
6
|
+
haml :index
|
7
|
+
end
|
8
|
+
|
9
|
+
get '/pie' do
|
10
|
+
data = params[:d].to_s.split(",").map(&:to_i)
|
11
|
+
|
12
|
+
r = 25
|
13
|
+
c = (2*Math::PI*r).ceil
|
14
|
+
v = data.first.to_f / data.last * 100 * c / 100
|
15
|
+
v = v.nan? ? 0 : v.ceil
|
16
|
+
|
17
|
+
content_type "image/svg+xml"
|
18
|
+
<<~BODY
|
19
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"
|
20
|
+
style="transform:rotate(-90deg);">
|
21
|
+
<circle r="#{r*2}" cx="50" cy="50" fill="#FFEBCC" />
|
22
|
+
<circle r="#{r}" cx="50" cy="50"
|
23
|
+
fill="transparent" stroke="#FF9901"
|
24
|
+
stroke-width="#{r*2}" stroke-dasharray="#{v} #{c}"
|
25
|
+
/>
|
26
|
+
</svg>
|
27
|
+
BODY
|
28
|
+
end
|
29
|
+
|
30
|
+
get '/:address' do
|
31
|
+
@host = find_host params[:address]
|
32
|
+
@host ? haml(:host) : halt(404)
|
33
|
+
end
|
34
|
+
|
35
|
+
def find_host address
|
36
|
+
@hosts.find { |h| h.address == address }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/amnesia/views/host.haml
CHANGED
@@ -1,24 +1,32 @@
|
|
1
|
-
%h2
|
2
|
-
%
|
1
|
+
%h2.host
|
2
|
+
%span.host-address
|
3
|
+
= @host.address
|
4
|
+
%small.host-details
|
5
|
+
= "#{@host.curr_items} item/s in cache, with #{@host.curr_connections} active connections"
|
3
6
|
|
4
|
-
%
|
5
|
-
%
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
%article.stats
|
8
|
+
%section.stats-graph
|
9
|
+
%img{src: graph_url(@host.bytes, @host.limit_maxbytes), width: 90}
|
10
|
+
%section.stats-text
|
11
|
+
%h3
|
12
|
+
%span.graph-indicator Used (#{number_to_human_size(@host.bytes)})
|
13
|
+
\/ Available Memory (#{number_to_human_size(@host.limit_maxbytes)})
|
14
|
+
%p The cumulative amount of available memory across all active hosts.
|
10
15
|
|
16
|
+
%article.stats
|
17
|
+
%section.stats-graph
|
18
|
+
%img{src: graph_url(@host.get_hits, @host.get_misses), width: 90}
|
19
|
+
%section.stats-text
|
20
|
+
%h3
|
21
|
+
%span.graph-indicator Hit (#{@host.get_hits})
|
22
|
+
\/ Miss (#{@host.get_misses})
|
23
|
+
%p The amount of returned caches vs misses, misses usually require your application servers to work harder.
|
11
24
|
|
12
|
-
%section.stats
|
13
|
-
%
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
%
|
20
|
-
%img{:src => graph_url([@host.cmd_get, @host.cmd_set]) }
|
21
|
-
%h3
|
22
|
-
%span.graph-indicator Read (#{@host.cmd_get})
|
23
|
-
\/ Write (#{@host.cmd_set})
|
24
|
-
%p More writes than reads can often mean that you’re caching too early, or that you’ve not been monitoring for very long.
|
25
|
+
%section.stats
|
26
|
+
%section.stats-graph
|
27
|
+
%img{src: graph_url(@host.cmd_get, @host.cmd_set), width: 90}
|
28
|
+
%section.stats-text
|
29
|
+
%h3
|
30
|
+
%span.graph-indicator Read (#{@host.cmd_get})
|
31
|
+
\/ Write (#{@host.cmd_set})
|
32
|
+
%p More writes than reads can often mean that you’re caching too early, or that you’ve not been monitoring for very long.
|
@@ -1,34 +1,39 @@
|
|
1
|
-
- if
|
2
|
-
%
|
3
|
-
%section.stats
|
4
|
-
%img{:
|
1
|
+
- if alive_hosts.any?
|
2
|
+
%article.stats
|
3
|
+
%section.stats-graph
|
4
|
+
%img{src: graph_url(bytes_sum, limit_maxbytes_sum), width: 90}
|
5
|
+
%section.stats-text
|
5
6
|
%h3
|
6
|
-
%span.graph-indicator
|
7
|
-
\/
|
7
|
+
%span.graph-indicator Used (#{number_to_human_size(bytes_sum)})
|
8
|
+
\/ Available Memory (#{number_to_human_size(limit_maxbytes_sum)})
|
9
|
+
%p The cumulative amount of available memory across all active hosts.
|
10
|
+
|
11
|
+
%article.stats
|
12
|
+
%section.stats-graph
|
13
|
+
%img{src: graph_url(get_hits_sum, get_misses_sum), width: 90}
|
14
|
+
%section.stats-text
|
15
|
+
%h3
|
16
|
+
%span.graph-indicator Hit (#{get_hits_sum})
|
17
|
+
\/ Miss (#{get_misses_sum})
|
8
18
|
%p The amount of returned caches vs misses, misses usually require your application servers to work harder.
|
9
|
-
|
10
|
-
|
19
|
+
|
20
|
+
%article.stats
|
21
|
+
%section.stats-graph
|
22
|
+
%img{src: graph_url(cmd_get_sum, cmd_set_sum), width: 90}
|
23
|
+
%section.stats-text
|
11
24
|
%h3
|
12
|
-
%span.graph-indicator Read
|
13
|
-
\/ Write
|
25
|
+
%span.graph-indicator Read (#{cmd_get_sum})
|
26
|
+
\/ Write (#{cmd_set_sum})
|
14
27
|
%p More writes than reads can often mean that you’re caching too early, or that you’ve not been monitoring for very long.
|
15
|
-
|
16
|
-
%section.stats.graph
|
17
|
-
%img{:src => graph_url([@hosts.collect{|h| h.bytes if h.alive? }.compact.sum, @hosts.collect{|h| h.limit_maxbytes if h.alive? }.compact.sum])}
|
18
|
-
%h3
|
19
|
-
%span.graph-indicator Used Memory
|
20
|
-
\/ Free Memory
|
21
|
-
%p The cumulative amount of free memory and total memory across all active hosts.
|
22
28
|
|
23
|
-
%nav
|
24
|
-
%p.sub
|
29
|
+
%nav
|
30
|
+
%p.sub Known Hosts
|
25
31
|
%ul
|
26
32
|
- for host in @hosts
|
27
33
|
- if host.alive?
|
28
|
-
%li
|
29
|
-
%a{:
|
34
|
+
%li.alive-host
|
35
|
+
%a{href: url("/#{host.address}") }= host.address
|
30
36
|
- else
|
31
|
-
%li.
|
37
|
+
%li.dead-host
|
32
38
|
= host.address
|
33
39
|
(Inactive)
|
34
|
-
|
@@ -1,19 +1,19 @@
|
|
1
1
|
!!!
|
2
2
|
%html
|
3
3
|
%head
|
4
|
-
%meta{:
|
4
|
+
%meta{charset: "utf-8"}
|
5
5
|
%title Amnesia
|
6
|
-
%link{:
|
6
|
+
%link{rel: "stylesheet", href: url("/css/application.css")}
|
7
7
|
%body
|
8
8
|
%header
|
9
|
-
%h1
|
10
|
-
%a{:
|
9
|
+
%h1.brand
|
10
|
+
%a{href: url('/')} Amnesia
|
11
11
|
%p Statistics for Memcached. Wait—What?
|
12
|
-
%
|
12
|
+
%main
|
13
13
|
= yield
|
14
14
|
%footer
|
15
|
-
%p
|
15
|
+
%p
|
16
16
|
Another
|
17
|
-
%a{:
|
18
|
-
joint. Get the
|
19
|
-
%a{:
|
17
|
+
%a{href: "http://germanforblack.com"} Ben Schwarz
|
18
|
+
joint. Get the
|
19
|
+
%a{href: "http://github.com/benschwarz/amnesia"} Source.
|
data/lib/amnesia.rb
CHANGED
@@ -1,55 +1,27 @@
|
|
1
|
-
require 'sinatra'
|
2
|
-
require 'memcache'
|
3
|
-
require 'gchart'
|
1
|
+
require 'sinatra/base'
|
4
2
|
require 'haml'
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
require 'amnesia/authentication'
|
4
|
+
require 'amnesia/helpers'
|
8
5
|
require 'amnesia/host'
|
9
|
-
require '
|
6
|
+
require 'amnesia/routes'
|
10
7
|
|
11
8
|
module Amnesia
|
12
|
-
class << self
|
13
|
-
attr_accessor :config
|
14
|
-
end
|
15
|
-
|
16
9
|
class Application < Sinatra::Base
|
17
|
-
|
18
|
-
|
10
|
+
include Amnesia::Authentication
|
11
|
+
include Amnesia::Helpers
|
12
|
+
include Amnesia::Routes
|
19
13
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
def graph_url(data = [])
|
27
|
-
GChart.pie(:data => data, :size => '115x115').to_url
|
28
|
-
end
|
29
|
-
|
30
|
-
def number_to_human_size(size, precision=1)
|
31
|
-
size = Kernel.Float(size)
|
32
|
-
case
|
33
|
-
when size.to_i == 1; "1 Byte"
|
34
|
-
when size < 1.kilobyte; "%d Bytes" % size
|
35
|
-
when size < 1.megabyte; "%.#{precision}f KB" % (size / 1.0.kilobyte)
|
36
|
-
when size < 1.gigabyte; "%.#{precision}f MB" % (size / 1.0.megabyte)
|
37
|
-
when size < 1.terabyte; "%.#{precision}f GB" % (size / 1.0.gigabyte)
|
38
|
-
else "%.#{precision}f TB" % (size / 1.0.terabyte)
|
39
|
-
end.sub(/([0-9])\.?0+ /, '\1 ' )
|
40
|
-
rescue
|
41
|
-
nil
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
get '/amnesia' do
|
46
|
-
@hosts = Amnesia.config[:hosts].map{|host| Host.new(host)}
|
47
|
-
haml :index
|
14
|
+
set :public_folder, File.join(__dir__, 'amnesia', 'public')
|
15
|
+
set :views, File.join(__dir__, 'amnesia', 'views')
|
16
|
+
|
17
|
+
def initialize(app = nil, options = {})
|
18
|
+
@hosts = build_hosts options[:hosts] || ENV['MEMCACHE_SERVERS'] || '127.0.0.1:11211'
|
19
|
+
super app
|
48
20
|
end
|
49
21
|
|
50
|
-
|
51
|
-
|
52
|
-
|
22
|
+
def build_hosts addresses
|
23
|
+
addresses = addresses.split "," if addresses.is_a? String
|
24
|
+
Array(addresses).flatten.map { |address| Amnesia::Host.new address }
|
53
25
|
end
|
54
26
|
end
|
55
|
-
end
|
27
|
+
end
|
metadata
CHANGED
@@ -1,138 +1,124 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: amnesia
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease: false
|
6
|
-
segments:
|
7
|
-
- 1
|
8
|
-
- 0
|
9
|
-
- 0
|
10
|
-
version: 1.0.0
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.1.0
|
11
5
|
platform: ruby
|
12
|
-
authors:
|
6
|
+
authors:
|
13
7
|
- Ben Schwarz
|
14
|
-
autorequire:
|
8
|
+
autorequire:
|
15
9
|
bindir: bin
|
16
10
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
dependencies:
|
21
|
-
- !ruby/object:Gem::Dependency
|
11
|
+
date: 2022-05-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
22
14
|
name: sinatra
|
23
|
-
|
24
|
-
|
25
|
-
none: false
|
26
|
-
requirements:
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
27
17
|
- - ">="
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
|
30
|
-
segments:
|
31
|
-
- 1
|
32
|
-
- 0
|
33
|
-
version: "1.0"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
34
20
|
type: :runtime
|
35
|
-
version_requirements: *id001
|
36
|
-
- !ruby/object:Gem::Dependency
|
37
|
-
name: memcache-client
|
38
21
|
prerelease: false
|
39
|
-
|
40
|
-
|
41
|
-
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: dalli
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
42
31
|
- - ">="
|
43
|
-
- !ruby/object:Gem::Version
|
44
|
-
|
45
|
-
segments:
|
46
|
-
- 1
|
47
|
-
- 5
|
48
|
-
- 0
|
49
|
-
version: 1.5.0
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
50
34
|
type: :runtime
|
51
|
-
version_requirements: *id002
|
52
|
-
- !ruby/object:Gem::Dependency
|
53
|
-
name: gchart
|
54
35
|
prerelease: false
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
segments:
|
62
|
-
- 1
|
63
|
-
- 0
|
64
|
-
- 0
|
65
|
-
version: 1.0.0
|
66
|
-
type: :runtime
|
67
|
-
version_requirements: *id003
|
68
|
-
- !ruby/object:Gem::Dependency
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
69
42
|
name: haml
|
70
|
-
|
71
|
-
|
72
|
-
none: false
|
73
|
-
requirements:
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
74
45
|
- - ">="
|
75
|
-
- !ruby/object:Gem::Version
|
76
|
-
|
77
|
-
segments:
|
78
|
-
- 3
|
79
|
-
- 0
|
80
|
-
- 0
|
81
|
-
version: 3.0.0
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
82
48
|
type: :runtime
|
83
|
-
|
84
|
-
|
85
|
-
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.9'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.9'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rack-test
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: With Amnesia you'll know exactly whats happening with memory when it
|
84
|
+
comes to memcached.
|
85
|
+
email:
|
86
86
|
- ben.schwarz@gmail.com
|
87
87
|
executables: []
|
88
|
-
|
89
88
|
extensions: []
|
90
|
-
|
91
89
|
extra_rdoc_files: []
|
92
|
-
|
93
|
-
|
90
|
+
files:
|
91
|
+
- LICENCE
|
92
|
+
- README.markdown
|
93
|
+
- lib/amnesia.rb
|
94
|
+
- lib/amnesia/authentication.rb
|
95
|
+
- lib/amnesia/helpers.rb
|
94
96
|
- lib/amnesia/host.rb
|
95
97
|
- lib/amnesia/public/css/application.css
|
98
|
+
- lib/amnesia/routes.rb
|
96
99
|
- lib/amnesia/views/host.haml
|
97
100
|
- lib/amnesia/views/index.haml
|
98
101
|
- lib/amnesia/views/layout.haml
|
99
|
-
- lib/amnesia.rb
|
100
|
-
- lib/core_ext/array.rb
|
101
|
-
- LICENCE
|
102
|
-
- README.markdown
|
103
|
-
has_rdoc: true
|
104
102
|
homepage: http://github.com/benschwarz/amnesia
|
105
103
|
licenses: []
|
106
|
-
|
107
|
-
post_install_message:
|
104
|
+
metadata: {}
|
105
|
+
post_install_message:
|
108
106
|
rdoc_options: []
|
109
|
-
|
110
|
-
require_paths:
|
107
|
+
require_paths:
|
111
108
|
- lib
|
112
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
113
|
-
|
114
|
-
requirements:
|
109
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
115
111
|
- - ">="
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
version: "0"
|
121
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
122
|
-
none: false
|
123
|
-
requirements:
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: '0'
|
114
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
124
116
|
- - ">="
|
125
|
-
- !ruby/object:Gem::Version
|
126
|
-
|
127
|
-
segments:
|
128
|
-
- 0
|
129
|
-
version: "0"
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0'
|
130
119
|
requirements: []
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
signing_key:
|
135
|
-
specification_version: 3
|
120
|
+
rubygems_version: 3.0.3
|
121
|
+
signing_key:
|
122
|
+
specification_version: 4
|
136
123
|
summary: Amnesia is what you get when you lose your memory
|
137
124
|
test_files: []
|
138
|
-
|