nutcracker-web 0.0.1

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 (40) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +10 -0
  3. data/Gemfile.lock +63 -0
  4. data/README.md +56 -0
  5. data/Rakefile +26 -0
  6. data/assets/javascripts/application.js +10 -0
  7. data/assets/javascripts/collections/clusters.js.coffee +4 -0
  8. data/assets/javascripts/collections/nodes.js.coffee +19 -0
  9. data/assets/javascripts/models/cluster.js.coffee +16 -0
  10. data/assets/javascripts/models/node.js.coffee +14 -0
  11. data/assets/javascripts/models/overview.js.coffee +27 -0
  12. data/assets/javascripts/nutcracker.js.coffee +20 -0
  13. data/assets/javascripts/routers/nutcracker_router.js.coffee +29 -0
  14. data/assets/javascripts/utils/region_manager.js.coffee +12 -0
  15. data/assets/javascripts/utils/underscore_ext.js.coffee +6 -0
  16. data/assets/javascripts/vendor/backbone.js +1571 -0
  17. data/assets/javascripts/vendor/bootstrap.js +2276 -0
  18. data/assets/javascripts/vendor/google_chart.js.coffee +124 -0
  19. data/assets/javascripts/vendor/humanize.js +459 -0
  20. data/assets/javascripts/vendor/jquery.js +8842 -0
  21. data/assets/javascripts/vendor/underscore.js +1227 -0
  22. data/assets/javascripts/views/cluster.js.coffee +58 -0
  23. data/assets/javascripts/views/config.js.coffee +6 -0
  24. data/assets/javascripts/views/footer.js.coffee +8 -0
  25. data/assets/javascripts/views/navbar.js.coffee +28 -0
  26. data/assets/javascripts/views/node.js.coffee +54 -0
  27. data/assets/javascripts/views/overview.js.coffee +6 -0
  28. data/assets/stylesheets/application.css +24 -0
  29. data/assets/stylesheets/bootstrap-responsive.css +1109 -0
  30. data/assets/stylesheets/bootstrap.css +6158 -0
  31. data/assets/templates/cluster.jst.eco +87 -0
  32. data/assets/templates/config.jst.eco +15 -0
  33. data/assets/templates/footer.jst.eco +1 -0
  34. data/assets/templates/navbar.jst.eco +55 -0
  35. data/assets/templates/node.jst.eco +73 -0
  36. data/assets/templates/overview.jst.eco +32 -0
  37. data/lib/nutcracker/web/app.rb +51 -0
  38. data/lib/nutcracker/web/version.rb +5 -0
  39. data/lib/nutcracker/web.rb +29 -0
  40. metadata +122 -0
@@ -0,0 +1,87 @@
1
+ <h3 align=center> <%= @model.get("name") %> </h3>
2
+
3
+ <ul class="pager fixed">
4
+ <%if @prevCluster: %>
5
+ <li class="previous nosel"><a class="nextPrevButton" href="<%= @prevCluster?.get("routeURL")%>">&larr; Prev</a></li>
6
+ <% else: %>
7
+ <li class="previous disabled nosel"><a>&larr; Prev</a></li>
8
+ <%end%>
9
+
10
+ <%if @nextCluster: %>
11
+ <li class="next nosel"><a class="nextPrevButton" href="<%= @nextCluster?.get("routeURL")%>">Next &rarr;</a></li>
12
+ <% else: %>
13
+ <li class="next disabled nosel"><a>Next &rarr;</a></li>
14
+ <%end%>
15
+ </li>
16
+ </ul>
17
+
18
+
19
+ </br>
20
+ <table class="table table-striped table-bordered">
21
+ <tr>
22
+ <th>Client Connections</th>
23
+ <th>Client EOF</th>
24
+ <th>Client Errors</th>
25
+ <th>Forward Errors</th>
26
+ <th>Fragments</th>
27
+ <th>Server Ejects</th>
28
+ </tr>
29
+ <tr>
30
+ <td><%= @model.get('client_connections')%></td>
31
+ <td><%= @model.get('client_eof')%></td>
32
+ <td><%= @model.get('client_err')%></td>
33
+ <td><%= @model.get('forward_error')%></td>
34
+ <td><%= @model.get('fragments')%></td>
35
+ <td><%= @model.get('server_ejects')%></td>
36
+ </tr>
37
+
38
+ </table>
39
+
40
+ </br>
41
+ <div class="chartsBox">
42
+ <div class="row">
43
+ <div class="span5">
44
+ <div id="chart1" style="padding-left: 23%"></div>
45
+ </div>
46
+ <div class="span5">
47
+ <div id="chart2" style="padding-left: 40%"></div>
48
+ </div>
49
+ </div>
50
+ </div>
51
+
52
+
53
+ </br>
54
+ <table class="table table-striped table-bordered">
55
+ <thead>
56
+ <tr>
57
+ <th>Host</th>
58
+ <th>Used Memory</th>
59
+ <th>Free Memory</th>
60
+ <th>Used Memory RSS</th>
61
+ <th>Max Memory</th>
62
+ <th>Fragmentation</th>
63
+ </tr>
64
+ </thead>
65
+ <tbody>
66
+ <% for node in @model.get("nodes").models: %>
67
+ <tr>
68
+ <td><a href="<%=node.get("routeURL")%>"><%=node.get("hostname")%></a></td>
69
+ <td><%=humanize.filesize node.get("usedMemory")%></td>
70
+ <td><%=humanize.filesize node.get("freeMemory")%></td>
71
+ <td><%=humanize.filesize node.get("usedMemoryRss")%></td>
72
+ <td><%=humanize.filesize node.get("maxMemory")%></td>
73
+ <td><%=node.get("fragmentation")%></td>
74
+ </tr>
75
+ <% end %>
76
+ <tr>
77
+ <td>&nbsp;</td>
78
+ <td><%=humanize.filesize _(@model.get("nodes").pluck("usedMemory")).sum()%></td>
79
+ <td><%=humanize.filesize _(@model.get("nodes").pluck("freeMemory")).sum()%></td>
80
+ <td><%=humanize.filesize _(@model.get("nodes").pluck("usedMemoryRss")).sum()%></td>
81
+ <td><%=humanize.filesize _(@model.get("nodes").pluck("maxMemory")).sum()%></td>
82
+ <td>~<%=humanize.numberFormat(_(@model.get("nodes").pluck("fragmentation")).average(),2)%></td>
83
+ </tr>
84
+ </tbody>
85
+ </table>
86
+
87
+
@@ -0,0 +1,15 @@
1
+
2
+ <h3> Clusters </h3>
3
+ <br/>
4
+ <% for conf in _(@model.get("config")).map( (v,k)->[k,v]): %>
5
+ <table class="table table-striped table-bordered">
6
+ <tr><th>Name</th><td><%-"<a href=#{Nutcracker.Models.Cluster.routeURL conf[0]}>#{conf[0]}</a>"%></td></tr>
7
+ <tr><th>Servers</th><td><%-conf[1].servers.map((s)->"<a href=#{Nutcracker.Models.Node.routeURL(s)}>#{s}</a>").join("<br/>")%></td></tr>
8
+ <% for array in _(conf[1]).map((v,k)->[k,v]): %>
9
+ <%if not /servers/.test array[0]:%>
10
+ <tr><th><%=array[0]%></th><td><%=array[1]%></td></tr>
11
+ <% end %>
12
+ <% end %>
13
+ </table>
14
+ </br>
15
+ <% end %>
@@ -0,0 +1 @@
1
+ Last Update <%=humanize.relativeTime(@model.get('timestamp'))%>
@@ -0,0 +1,55 @@
1
+ <div class="navbar">
2
+ <div class="navbar-inner">
3
+ <div class="container" style="font-size: 17px">
4
+ <a class="btn btn-navbar" data-toggle="collapse" data-target=".navbar-responsive-collapse">
5
+ <span class="icon-bar"></span>
6
+ <span class="icon-bar"></span>
7
+ <span class="icon-bar"></span>
8
+ </a>
9
+ <a class="brand" href="#" style="color: #ffffff;font-size: 25px">Nutcracker</a>
10
+ <div class="nav-collapse collapse navbar-responsive-collapse">
11
+ <ul class="nav">
12
+ <li class="divider-vertical"></li>
13
+ <li id="overview" ><a href="#/">Overview</a></li>
14
+ <li class="divider-vertical"></li>
15
+ <li id="config" ><a href="#/config">Config </a></li>
16
+ <li class="divider-vertical"></li>
17
+ <li id="clusters" class="dropdown">
18
+ <a class="dropdown-toggle" id="drop4" style="padding-top: 12px;" role="button" data-toggle="dropdown" href="#">Clusters <b class="caret"></b></a>
19
+ <ul id="menu1" class="dropdown-menu" role="menu" aria-labelledby="drop4">
20
+ <li class='divider'></li>
21
+ <% for cluster in @model.get("clusters").models: %>
22
+ <li role="presentation" style="font-size: 15px">
23
+ <a role="menuitem" tabindex="-1" href="<%=cluster.get('routeURL')%>"><%=cluster.get('name')%></a>
24
+ </li>
25
+ <li class='divider'></li>
26
+ <% end %>
27
+ </ul>
28
+ </li>
29
+
30
+ <li class="divider-vertical"></li>
31
+ <li id="nodes" class="dropdown">
32
+ <a class="dropdown-toggle" id="drop5" style="padding-top: 12px;" role="button" data-toggle="dropdown" href="#">Nodes <b class="caret"></b></a>
33
+ <ul id="menu1" class="dropdown-menu" role="menu" aria-labelledby="drop5">
34
+ <li class='divider'></li>
35
+ <% for node in @model.nodes().models: %>
36
+ <li role="presentation" style="font-size: 15px">
37
+ <a role="menuitem" tabindex="-1" href="<%=node.get("routeURL")%>"><%=node.get("hostname")%></a>
38
+ </li>
39
+ <li class='divider'></li>
40
+ <% end %>
41
+ </ul>
42
+ </li>
43
+
44
+ <li class="divider-vertical"></li>
45
+ </ul>
46
+
47
+ <ul class="nav pull-right">
48
+ <li class="divider-vertical"></li>
49
+ <li class="no-hl"><a>Version <%=@model.get("version")%></a></li>
50
+ <li class="divider-vertical"></li>
51
+ </ul>
52
+ </div><!-- /.nav-collapse -->
53
+ </div>
54
+ </div><!-- /navbar-inner -->
55
+ </div><!-- /navbar -->
@@ -0,0 +1,73 @@
1
+ <h3 align=center><%= @model.get("hostname") %></h3>
2
+
3
+ <ul class="pager">
4
+ <%if @prevNode: %>
5
+ <li class="previous nosel"><a class="nextPrevButton" href="<%= @prevNode?.get("routeURL")%>">&larr; Prev</a></li>
6
+ <% else: %>
7
+ <li class="previous disabled nosel"><a>&larr; Prev</a></li>
8
+ <%end%>
9
+
10
+ <% for cluster in @model.get("clusters"): %>
11
+ <li class="nosel"><a class="nextPrevButton" href="<%= cluster.get('routeURL')%>"><%=cluster.get('name')%></a></li>
12
+ <% end %>
13
+
14
+ <%if @nextNode: %>
15
+ <li class="next nosel"><a class="nextPrevButton" href="<%= @nextNode?.get("routeURL")%>">Next &rarr;</a></li>
16
+ <% else: %>
17
+ <li class="next disabled nosel"><a>Next &rarr;</a></li>
18
+ <%end%>
19
+ </li>
20
+ </ul>
21
+ </br>
22
+ <div class="chartsBox">
23
+ <div class="row">
24
+ <div class="span5">
25
+ <div id="chart1" style="padding-left: 26%"></div>
26
+ </div>
27
+ <div class="span5">
28
+ <div id="chart2" style="padding-left: 40%"></div>
29
+ </div>
30
+ </div>
31
+ </div>
32
+
33
+ <br/>
34
+ <div class="row-fluid">
35
+ <div class="span6">
36
+ <h4> Cluster <-> Node Stats </h4>
37
+ <table class="table table-striped table-bordered">
38
+ <tr><th>In-Queue</th><td> <%= @model.get "in_queue" %></td></tr>
39
+ <tr><th>In-Queue Memory Size</th><td> <%= humanize.filesize(@model.get "in_queue_bytes") %></td></tr>
40
+ <tr><th>Out-Queue</th><td> <%= @model.get "out_queue" %></td></tr>
41
+ <tr><th>Out-Queue Memory Size</th><td> <%= humanize.filesize(@model.get "out_queue_bytes") %></td></tr>
42
+ <tr><th>Requests</th><td> <%= @model.get "requests" %></td></tr>
43
+ <tr><th>Requests Memory Size</th><td> <%= humanize.filesize(@model.get "request_bytes") %></td></tr>
44
+ <tr><th>Responses</th><td> <%= @model.get "responses" %></td></tr>
45
+ <tr><th>Responses Memory Size</th><td> <%= humanize.filesize(@model.get "response_bytes") %></td></tr>
46
+ <tr><th>Server Connections</th><td> <%= @model.get "server_connections" %></td></tr>
47
+ <tr><th>Server EOF</th><td> <%= @model.get "server_eof" %></td></tr>
48
+ <tr><th>Server Error</th><td> <%= @model.get "server_err" %></td></tr>
49
+ <tr><th>Server Timedout</th><td> <%= @model.get "server_timedout" %></td></tr>
50
+ </table>
51
+ </div>
52
+
53
+ <div class="span6">
54
+ <h4>Node Stats</h3>
55
+ <table class="table table-striped table-bordered">
56
+ <tr><th>Hits</th><td> <%= humanize.numberFormat @model.get("info").hits, 0 %></td></tr>
57
+ <tr><th>Misses</th><td> <%= humanize.numberFormat @model.get("info").misses, 0 %></td></tr>
58
+ <tr><th>Hit Ratio</th><td> <%= humanize.numberFormat @model.get("info").hit_ratio, 2 %></td></tr>
59
+ <tr><th>Max Memory</th><td> <%= humanize.filesize @model.get("info").max_memory %></td></tr>
60
+ <tr><th>Used Memory</th><td> <%= humanize.filesize @model.get("info").used_memory %></td></tr>
61
+ <tr><th>Used Memory RSS</th><td> <%= humanize.filesize @model.get("info").used_memory_rss %></td></tr>
62
+ <tr><th>Connections</th><td> <%= @model.get("info").connections %></td></tr>
63
+ <tr><th>Keys</th><td> <%= humanize.numberFormat @model.get("info").keys , 0%></td></tr>
64
+ <tr><th>Evicted Keys</th><td> <%= humanize.numberFormat @model.get("info").evicted_keys, 0 %></td></tr>
65
+ <tr><th>Expired Keys</th><td> <%= humanize.numberFormat @model.get("info").expired_keys, 0 %></td></tr>
66
+ <tr><th>Fragmentation</th><td> <%= humanize.numberFormat @model.get("info").fragmentation, 2 %></td></tr>
67
+ <tr><th>&nbsp;</th><td> &nbsp;</td></tr>
68
+ </table>
69
+ </div>
70
+
71
+ </div>
72
+
73
+
@@ -0,0 +1,32 @@
1
+ <h3> Overview </h3>
2
+ <br/>
3
+ <table class="table table-striped table-bordered">
4
+ <tbody>
5
+ <tr><th>Hostname</th><td><%=@model.get("source")%></td></tr>
6
+ <tr><th>Service</th><td>Nutcracker Ver. <%=@model.get("version")%></td></tr>
7
+ <tr><th>Uptime</th><td><%=humanize.relativeTime(((new Date())-@model.get("uptime")*1000)/1000)%></td></tr>
8
+ <tr><th>Server Connections</th><td><%=@model.get("serverConnections")%></td></tr>
9
+ <tr><th>Client Connections</th><td><%=@model.get("clientConnections")%></td></tr>
10
+
11
+ <tr>
12
+ <th>Total Clusters</th>
13
+ <td>
14
+ <% for cluster in @model.get("clusters").models: %>
15
+ <a href="<%=cluster.get("routeURL")%>"><%=cluster.get("name")%></a><br/>
16
+ <%end%>
17
+ </td>
18
+ </tr>
19
+
20
+ <tr>
21
+ <th>Total Nodes</th>
22
+ <td>
23
+ <% for node in @model.nodes().models: %>
24
+ <a href="<%=node.get('routeURL')%>"><%=node.get('hostname')%></a><br/>
25
+ <%end%>
26
+ </td>
27
+ </tr>
28
+
29
+
30
+ </tbody>
31
+ </table>
32
+
@@ -0,0 +1,51 @@
1
+ require 'haml'
2
+ require 'sinatra'
3
+ require 'eco'
4
+ require 'sprockets'
5
+ require 'json'
6
+
7
+ module Nutcracker
8
+ module Web
9
+ class App < Sinatra::Base
10
+ enable :inline_templates
11
+ set :root, File.expand_path('../'*4,__FILE__)
12
+ set :assets, Sprockets::Environment.new { |env|
13
+ %w(javascripts stylesheets templates).each { |asset|
14
+ env.append_path File.join(settings.root,"assets/#{asset}")
15
+ }
16
+ }
17
+
18
+ get '/' do
19
+ haml :index
20
+ end
21
+
22
+ def overview
23
+ Thread.current[:nutcracker].overview rescue
24
+ JSON.parse File.read File.join(settings.root,"example.json")
25
+ end
26
+
27
+ end
28
+ end
29
+ end
30
+
31
+ __END__
32
+
33
+ @@ layout
34
+ %html
35
+ %head
36
+ %title Nutcracker-Web
37
+ %script(type='text/javascript' src='http://www.google.com/jsapi')
38
+ %script(type='text/javascript' src='assets/application.js')
39
+ %link(rel='stylesheet' href='assets/application.css')
40
+ %link(rel="shortcut icon" href="http://publishers.kontera.com/favicon.ico")
41
+ %body
42
+ = yield
43
+
44
+ @@ index
45
+ #navbar
46
+ .container
47
+ #container{ "data-clusters" => overview.to_json }
48
+ loading...
49
+ #footer
50
+ - 3.times do
51
+ %br
@@ -0,0 +1,5 @@
1
+ module Nutcracker
2
+ module Web
3
+ VERSION="0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,29 @@
1
+ require "rack"
2
+
3
+ module Nutcracker
4
+ module Web
5
+ def self.start nutcracker, options
6
+ @thread = Thread.new do
7
+ Thread.current.abort_on_exception=true
8
+ Thread.current[:nutcracker] = nutcracker
9
+ Rack::Server.start(
10
+ {
11
+ :environment => 'development',
12
+ :pid => nil,
13
+ :Port => 9393,
14
+ :Host => '0.0.0.0',
15
+ :AccessLog => [],
16
+ :config => File.expand_path("../../../config.ru", __FILE__)
17
+ }.merge( options )
18
+ )
19
+ end
20
+ self
21
+ end
22
+
23
+ def self.stop
24
+ @thread.kill
25
+ end
26
+
27
+ autoload :App, 'nutcracker/web/app'
28
+ end
29
+ end
metadata ADDED
@@ -0,0 +1,122 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nutcracker-web
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Eran Barak Levi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-07-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: minitest
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 5.0.0
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 5.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: mocha
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: 0.14.0
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: 0.14.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: nutcracker
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: 0.2.4.5
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 0.2.4.5
55
+ description: Web interface for Nutcracker cluster
56
+ email: eran@kontera.com
57
+ executables: []
58
+ extensions: []
59
+ extra_rdoc_files: []
60
+ files:
61
+ - README.md
62
+ - Rakefile
63
+ - Gemfile
64
+ - Gemfile.lock
65
+ - lib/nutcracker/web/app.rb
66
+ - lib/nutcracker/web/version.rb
67
+ - lib/nutcracker/web.rb
68
+ - assets/javascripts/application.js
69
+ - assets/javascripts/collections/clusters.js.coffee
70
+ - assets/javascripts/collections/nodes.js.coffee
71
+ - assets/javascripts/models/cluster.js.coffee
72
+ - assets/javascripts/models/node.js.coffee
73
+ - assets/javascripts/models/overview.js.coffee
74
+ - assets/javascripts/nutcracker.js.coffee
75
+ - assets/javascripts/routers/nutcracker_router.js.coffee
76
+ - assets/javascripts/utils/region_manager.js.coffee
77
+ - assets/javascripts/utils/underscore_ext.js.coffee
78
+ - assets/javascripts/vendor/backbone.js
79
+ - assets/javascripts/vendor/bootstrap.js
80
+ - assets/javascripts/vendor/google_chart.js.coffee
81
+ - assets/javascripts/vendor/humanize.js
82
+ - assets/javascripts/vendor/jquery.js
83
+ - assets/javascripts/vendor/underscore.js
84
+ - assets/javascripts/views/cluster.js.coffee
85
+ - assets/javascripts/views/config.js.coffee
86
+ - assets/javascripts/views/footer.js.coffee
87
+ - assets/javascripts/views/navbar.js.coffee
88
+ - assets/javascripts/views/node.js.coffee
89
+ - assets/javascripts/views/overview.js.coffee
90
+ - assets/stylesheets/application.css
91
+ - assets/stylesheets/bootstrap-responsive.css
92
+ - assets/stylesheets/bootstrap.css
93
+ - assets/templates/cluster.jst.eco
94
+ - assets/templates/config.jst.eco
95
+ - assets/templates/footer.jst.eco
96
+ - assets/templates/navbar.jst.eco
97
+ - assets/templates/node.jst.eco
98
+ - assets/templates/overview.jst.eco
99
+ homepage: http://www.kontera.com
100
+ licenses: []
101
+ metadata: {}
102
+ post_install_message:
103
+ rdoc_options: []
104
+ require_paths:
105
+ - lib
106
+ required_ruby_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: 1.9.1
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - '>='
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ requirements: []
117
+ rubyforge_project: ruby-nutcracker-web
118
+ rubygems_version: 2.0.3
119
+ signing_key:
120
+ specification_version: 4
121
+ summary: Nutcracker Web Interface
122
+ test_files: []