memdash 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 (39) hide show
  1. data/.gitignore +18 -0
  2. data/.rspec +2 -0
  3. data/.travis.yml +5 -0
  4. data/Gemfile +3 -0
  5. data/LICENSE +22 -0
  6. data/README.md +58 -0
  7. data/Rakefile +22 -0
  8. data/config.ru +7 -0
  9. data/lib/generators/memdash/active_record_generator.rb +17 -0
  10. data/lib/generators/memdash/templates/migration.rb +12 -0
  11. data/lib/memdash.rb +9 -0
  12. data/lib/memdash/active_record.rb +2 -0
  13. data/lib/memdash/active_record/client.rb +13 -0
  14. data/lib/memdash/active_record/report.rb +13 -0
  15. data/lib/memdash/client.rb +26 -0
  16. data/lib/memdash/configuration.rb +11 -0
  17. data/lib/memdash/server.rb +50 -0
  18. data/lib/memdash/server/public/charts.js +136 -0
  19. data/lib/memdash/server/public/cross_scratches.png +0 -0
  20. data/lib/memdash/server/public/jqplot.canvasAxisTickRenderer.js +243 -0
  21. data/lib/memdash/server/public/jqplot.canvasAxisTickRenderer.min.js +57 -0
  22. data/lib/memdash/server/public/jqplot.canvasTextRenderer.min.js +57 -0
  23. data/lib/memdash/server/public/jqplot.dateAxisRenderer.min.js +57 -0
  24. data/lib/memdash/server/public/jquery.jqplot.min.css +1 -0
  25. data/lib/memdash/server/public/jquery.jqplot.min.js +57 -0
  26. data/lib/memdash/server/public/reset.css +260 -0
  27. data/lib/memdash/server/public/style.css +66 -0
  28. data/lib/memdash/server/views/application.erb +24 -0
  29. data/lib/memdash/server/views/overview.erb +19 -0
  30. data/memdash.gemspec +25 -0
  31. data/screenshot.png +0 -0
  32. data/spec/memdash_spec.rb +31 -0
  33. data/spec/spec_helper.rb +3 -0
  34. data/spec/support/adapters/active_record.rb +11 -0
  35. data/spec/support/dalli.rb +15 -0
  36. data/spec/support/database_cleaner.rb +16 -0
  37. data/spec/support/memcached.rb +6 -0
  38. data/spec/support/schema.rb +12 -0
  39. metadata +204 -0
@@ -0,0 +1,260 @@
1
+ /* http://meyerweb.com/eric/tools/css/reset/
2
+ v2.0 | 20110126
3
+ License: none (public domain)
4
+ */
5
+
6
+ html, body, div, span, applet, object, iframe,
7
+ h1, h2, h3, h4, h5, h6, p, blockquote, pre,
8
+ a, abbr, acronym, address, big, cite, code,
9
+ del, dfn, em, img, ins, kbd, q, s, samp,
10
+ small, strike, strong, sub, sup, tt, var,
11
+ b, u, i, center,
12
+ dl, dt, dd, ol, ul, li,
13
+ fieldset, form, label, legend,
14
+ table, caption, tbody, tfoot, thead, tr, th, td,
15
+ article, aside, canvas, details, embed,
16
+ figure, figcaption, footer, header, hgroup,
17
+ menu, nav, output, ruby, section, summary,
18
+ time, mark, audio, video {
19
+ margin: 0;
20
+ padding: 0;
21
+ border: 0;
22
+ font-size: 100%;
23
+ font: inherit;
24
+ vertical-align: baseline;
25
+ }
26
+ /* HTML5 display-role reset for older browsers */
27
+ article, aside, details, figcaption, figure,
28
+ footer, header, hgroup, menu, nav, section {
29
+ display: block;
30
+ }
31
+ body {
32
+ line-height: 1;
33
+ }
34
+ ol, ul {
35
+ list-style: none;
36
+ }
37
+ blockquote, q {
38
+ quotes: none;
39
+ }
40
+ blockquote:before, blockquote:after,
41
+ q:before, q:after {
42
+ content: '';
43
+ content: none;
44
+ }
45
+ table {
46
+ border-collapse: collapse;
47
+ border-spacing: 0;
48
+ }
49
+ /*!
50
+ * Bootstrap v2.0.2
51
+ *
52
+ * Copyright 2012 Twitter, Inc
53
+ * Licensed under the Apache License v2.0
54
+ * http://www.apache.org/licenses/LICENSE-2.0
55
+ *
56
+ * Designed and built with all the love in the world @twitter by @mdo and @fat.
57
+ */
58
+ .clearfix {
59
+ *zoom: 1;
60
+ }
61
+ .clearfix:before,
62
+ .clearfix:after {
63
+ display: table;
64
+ content: "";
65
+ }
66
+ .clearfix:after {
67
+ clear: both;
68
+ }
69
+ .hide-text {
70
+ overflow: hidden;
71
+ text-indent: 100%;
72
+ white-space: nowrap;
73
+ }
74
+ .input-block-level {
75
+ display: block;
76
+ width: 100%;
77
+ min-height: 28px;
78
+ /* Make inputs at least the height of their button counterpart */
79
+
80
+ /* Makes inputs behave like true block-level elements */
81
+
82
+ -webkit-box-sizing: border-box;
83
+ -moz-box-sizing: border-box;
84
+ -ms-box-sizing: border-box;
85
+ box-sizing: border-box;
86
+ }
87
+ .row {
88
+ margin-left: -20px;
89
+ *zoom: 1;
90
+ }
91
+ .row:before,
92
+ .row:after {
93
+ display: table;
94
+ content: "";
95
+ }
96
+ .row:after {
97
+ clear: both;
98
+ }
99
+ [class*="span"] {
100
+ float: left;
101
+ margin-left: 20px;
102
+ }
103
+ .container,
104
+ .navbar-fixed-top .container,
105
+ .navbar-fixed-bottom .container {
106
+ width: 940px;
107
+ }
108
+ .span12 {
109
+ width: 940px;
110
+ }
111
+ .span11 {
112
+ width: 860px;
113
+ }
114
+ .span10 {
115
+ width: 780px;
116
+ }
117
+ .span9 {
118
+ width: 700px;
119
+ }
120
+ .span8 {
121
+ width: 620px;
122
+ }
123
+ .span7 {
124
+ width: 540px;
125
+ }
126
+ .span6 {
127
+ width: 460px;
128
+ }
129
+ .span5 {
130
+ width: 380px;
131
+ }
132
+ .span4 {
133
+ width: 300px;
134
+ }
135
+ .span3 {
136
+ width: 220px;
137
+ }
138
+ .span2 {
139
+ width: 140px;
140
+ }
141
+ .span1 {
142
+ width: 60px;
143
+ }
144
+ .offset12 {
145
+ margin-left: 980px;
146
+ }
147
+ .offset11 {
148
+ margin-left: 900px;
149
+ }
150
+ .offset10 {
151
+ margin-left: 820px;
152
+ }
153
+ .offset9 {
154
+ margin-left: 740px;
155
+ }
156
+ .offset8 {
157
+ margin-left: 660px;
158
+ }
159
+ .offset7 {
160
+ margin-left: 580px;
161
+ }
162
+ .offset6 {
163
+ margin-left: 500px;
164
+ }
165
+ .offset5 {
166
+ margin-left: 420px;
167
+ }
168
+ .offset4 {
169
+ margin-left: 340px;
170
+ }
171
+ .offset3 {
172
+ margin-left: 260px;
173
+ }
174
+ .offset2 {
175
+ margin-left: 180px;
176
+ }
177
+ .offset1 {
178
+ margin-left: 100px;
179
+ }
180
+ .row-fluid {
181
+ width: 100%;
182
+ *zoom: 1;
183
+ }
184
+ .row-fluid:before,
185
+ .row-fluid:after {
186
+ display: table;
187
+ content: "";
188
+ }
189
+ .row-fluid:after {
190
+ clear: both;
191
+ }
192
+ .row-fluid > [class*="span"] {
193
+ float: left;
194
+ margin-left: 2.127659574%;
195
+ }
196
+ .row-fluid > [class*="span"]:first-child {
197
+ margin-left: 0;
198
+ }
199
+ .row-fluid > .span12 {
200
+ width: 99.99999998999999%;
201
+ }
202
+ .row-fluid > .span11 {
203
+ width: 91.489361693%;
204
+ }
205
+ .row-fluid > .span10 {
206
+ width: 82.97872339599999%;
207
+ }
208
+ .row-fluid > .span9 {
209
+ width: 74.468085099%;
210
+ }
211
+ .row-fluid > .span8 {
212
+ width: 65.95744680199999%;
213
+ }
214
+ .row-fluid > .span7 {
215
+ width: 57.446808505%;
216
+ }
217
+ .row-fluid > .span6 {
218
+ width: 48.93617020799999%;
219
+ }
220
+ .row-fluid > .span5 {
221
+ width: 40.425531911%;
222
+ }
223
+ .row-fluid > .span4 {
224
+ width: 31.914893614%;
225
+ }
226
+ .row-fluid > .span3 {
227
+ width: 23.404255317%;
228
+ }
229
+ .row-fluid > .span2 {
230
+ width: 14.89361702%;
231
+ }
232
+ .row-fluid > .span1 {
233
+ width: 6.382978723%;
234
+ }
235
+ .container {
236
+ margin-left: auto;
237
+ margin-right: auto;
238
+ *zoom: 1;
239
+ }
240
+ .container:before,
241
+ .container:after {
242
+ display: table;
243
+ content: "";
244
+ }
245
+ .container:after {
246
+ clear: both;
247
+ }
248
+ .container-fluid {
249
+ padding-left: 20px;
250
+ padding-right: 20px;
251
+ *zoom: 1;
252
+ }
253
+ .container-fluid:before,
254
+ .container-fluid:after {
255
+ display: table;
256
+ content: "";
257
+ }
258
+ .container-fluid:after {
259
+ clear: both;
260
+ }
@@ -0,0 +1,66 @@
1
+ html {
2
+ background: #efefef url(cross_scratches.png) repeat 0 0;
3
+ font-family: Helvetica, sans-serif;
4
+ font-size: 16px;
5
+ font-weight: 700;
6
+ line-height: 24px;
7
+ color: #3e3e3e;
8
+ }
9
+ body {
10
+ padding: 0;
11
+ margin: 0;
12
+ }
13
+ .container {
14
+ text-shadow: 0 1px rgba(255,255,255,.8);
15
+ }
16
+ .hero-stats {
17
+ margin-bottom: 20px;
18
+ padding-top: 20px;
19
+ background: #fefefe;
20
+ color: #4d4d4d;
21
+ border-bottom: 1px solid rgba(0,0,0,.3);
22
+ box-shadow: 0 1px 2px rgba(0,0,0,.2);
23
+ }
24
+ .hero-stats .row {
25
+ margin-left: auto;
26
+ margin-bottom: 20px;
27
+ }
28
+ .hero-stats .row li:first-child {
29
+ margin-left: 0;
30
+ }
31
+ ol {
32
+ width: 940px;
33
+ margin: 0 auto;
34
+ }
35
+ li {
36
+ font-weight: 300;
37
+ }
38
+ .count {
39
+ font-weight: 700;
40
+ font-size: 48px;
41
+ display: block;
42
+ }
43
+ .row {
44
+ margin-bottom: 40px;
45
+ }
46
+
47
+ footer {
48
+ margin: 0;
49
+ padding: 8px 0 30px 0;
50
+ font-size: 13px;
51
+ font-weight: 300;
52
+ text-align: right;
53
+ background: #fefefe;
54
+ border-top: 1px solid rgba(0,0,0,.2);
55
+ }
56
+ footer p {
57
+ width: 940px;
58
+ margin: 0 auto;
59
+ }
60
+
61
+ .jqplot-target {
62
+ font-family: Helvetica, sans-serif;
63
+ }
64
+ .jqplot-axis {
65
+ font-weight: 300;
66
+ }
@@ -0,0 +1,24 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>Memdash</title>
6
+ <link href="<%= u 'reset.css' %>" media="screen" rel="stylesheet" type="text/css">
7
+ <link href="<%= u 'jquery.jqplot.min.css' %>" media="screen" rel="stylesheet" type="text/css">
8
+ <link href="<%= u 'style.css' %>" media="screen" rel="stylesheet" type="text/css">
9
+ </head>
10
+ <body>
11
+ <%= yield %>
12
+
13
+ <footer>
14
+ <p>Powered by <a href="http://github.com/bryckbost/memdash">Memdash</a>.</p>
15
+ </footer>
16
+
17
+ <script src="http://code.jquery.com/jquery-1.7.2.min.js" type="text/javascript"></script>
18
+ <script src="<%= u 'jquery.jqplot.min.js' %>" type="text/javascript"></script>
19
+ <script src="<%= u 'jqplot.canvasTextRenderer.min.js' %>" type="text/javascript"></script>
20
+ <script src="<%= u 'jqplot.canvasAxisTickRenderer.min.js' %>" type="text/javascript"></script>
21
+ <script src="<%= u 'jqplot.dateAxisRenderer.min.js' %>" type="text/javascript"></script>
22
+ <script src="<%= u 'charts.js' %>" type="text/javascript"></script>
23
+ </body>
24
+ </html>
@@ -0,0 +1,19 @@
1
+ <div class="hero-stats">
2
+ <ol class="row">
3
+ <li class="span4"><span class="count"><%= miss_ratio_percentage(@last_report.stats.map{|_, v| v["get_hits"].to_f}.sum, @last_report.stats.map{|_, v| v["get_misses"].to_f}.sum).round(2) %>%</span>Cache miss ratio</li>
4
+ <li class="span4"><span class="count"><%= @last_report.stats.map{|_, v| v["curr_items"]}.sum %></span>Current items in memcache</li>
5
+ <li class="span4"><span class="count"><%= (@last_report.stats.map{|_,v| v["bytes"].to_i}.sum / 1024.0 / 1024.0).round(2) %>/<%= @last_report.stats.map{|_,v| v["limit_maxbytes"].to_i}.sum / 1024 / 1024 %> MB</span>Current memory usage</li>
6
+ </ol>
7
+ </div>
8
+
9
+ <section class="container">
10
+ <div class="row">
11
+ <div id="gets-sets" class="span6" data-gets='<%= @gets %>' data-sets='<%= @sets %>'></div>
12
+ <div id="hits-misses" class="span6" data-hits='<%= @hits %>' data-misses='<%= @misses %>'></div>
13
+ </div>
14
+
15
+ <div class="row">
16
+ <div id="memory-usage" class="span6" data-limit-maxbytes='<%= @limit_maxbytes %>' data-bytes='<%= @bytes %>'></div>
17
+ <div id="current-items" class="span6" data-current-items='<%= @current_items %>'></div>
18
+ </div>
19
+ </section>
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.name = 'memdash'
5
+ gem.version = '0.0.1'
6
+
7
+ gem.authors = ['Brian Ryckbost', 'Steve Richert']
8
+ gem.email = ['bryckbost@gmail.com', 'steve.richert@gmail.com']
9
+ gem.description = 'A dashboard for your memcache'
10
+ gem.summary = 'A dashboard for your memcache'
11
+ gem.homepage = 'https://github.com/bryckbost/memdash'
12
+
13
+ gem.add_dependency 'activerecord', '~> 3.0'
14
+ gem.add_dependency 'dalli', '~> 2.0'
15
+ gem.add_dependency 'sinatra', '~> 1.3'
16
+
17
+ gem.add_development_dependency 'database_cleaner'
18
+ gem.add_development_dependency 'rake'
19
+ gem.add_development_dependency 'rspec'
20
+ gem.add_development_dependency 'sqlite3'
21
+
22
+ gem.files = `git ls-files`.split($\)
23
+ gem.test_files = gem.files.grep(/^spec\//)
24
+ gem.require_paths = ['lib']
25
+ end
Binary file
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe Memdash do
4
+ before do
5
+ Memdash.ttl = 2
6
+ end
7
+
8
+ it 'records gets' do
9
+ expect{ dalli.get('key') }.to change{ reports_count }.by(1)
10
+ end
11
+
12
+ it 'waits between recording gets' do
13
+ dalli.get('key')
14
+ sleep 1
15
+ expect{ dalli.get('key') }.to_not change{ reports_count }
16
+ sleep 2
17
+ expect{ dalli.get('key') }.to change{ reports_count }.by(1)
18
+ end
19
+
20
+ it 'records sets' do
21
+ expect{ dalli.set('key', 'value') }.to change{ reports_count }.by(1)
22
+ end
23
+
24
+ it 'waits between recording sets' do
25
+ dalli.set('key', 'value')
26
+ sleep 1
27
+ expect{ dalli.set('key', 'value') }.to_not change{ reports_count }
28
+ sleep 2
29
+ expect{ dalli.set('key', 'value') }.to change{ reports_count }.by(1)
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ require "support/adapters/#{ENV['ADAPTER']}" if ENV['ADAPTER']
2
+
3
+ Dir[File.expand_path('../support/*.rb', __FILE__)].each{|f| require f }
@@ -0,0 +1,11 @@
1
+ require 'memdash/active_record'
2
+
3
+ module ActiveRecordHelpers
4
+ def reports_count
5
+ Memdash::ActiveRecord::Report.count
6
+ end
7
+ end
8
+
9
+ RSpec.configure do |config|
10
+ config.include ActiveRecordHelpers
11
+ end