all_seeing_eye 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +13 -0
- data/Gemfile.lock +30 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +19 -0
- data/Rakefile +51 -0
- data/VERSION +1 -0
- data/all_seeing_eye.gemspec +93 -0
- data/bin/all-seeing-eye +14 -0
- data/init.rb +1 -0
- data/lib/all_seeing_eye/integrations/rails2.rb +30 -0
- data/lib/all_seeing_eye/model.rb +163 -0
- data/lib/all_seeing_eye/models/request.rb +3 -0
- data/lib/all_seeing_eye/server/public/application.js +16 -0
- data/lib/all_seeing_eye/server/public/eye.png +0 -0
- data/lib/all_seeing_eye/server/public/jquery-1.6.2.min.js +18 -0
- data/lib/all_seeing_eye/server/public/jquery.equal_heights.js +13 -0
- data/lib/all_seeing_eye/server/public/jquery.flot.js +2651 -0
- data/lib/all_seeing_eye/server/public/reset.css +1 -0
- data/lib/all_seeing_eye/server/public/style.css +231 -0
- data/lib/all_seeing_eye/server/views/field.erb +69 -0
- data/lib/all_seeing_eye/server/views/layout.erb +40 -0
- data/lib/all_seeing_eye/server/views/left.erb +29 -0
- data/lib/all_seeing_eye/server/views/total.erb +95 -0
- data/lib/all_seeing_eye/server/views/view.erb +63 -0
- data/lib/all_seeing_eye/server.rb +135 -0
- data/lib/all_seeing_eye.rb +26 -0
- data/test/base_test.rb +11 -0
- data/test/fixtures/all_seeing_eye.yml +21 -0
- data/test/fixtures/redis-test.conf +115 -0
- data/test/model_test.rb +306 -0
- data/test/test_helper.rb +57 -0
- metadata +213 -0
@@ -0,0 +1 @@
|
|
1
|
+
html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:text-top;}sub{vertical-align:text-bottom;}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit;}input,textarea,select{*font-size:100%;}legend{color:#000;}
|
@@ -0,0 +1,231 @@
|
|
1
|
+
body {font-size: 0.8em; font-family: Verdana, Georgia, serif;}
|
2
|
+
|
3
|
+
h1 {font-size: 2em; width: 100%; margin: 20px 10px 10px 10px; text-shadow: 2px 2px 0 #eee;}
|
4
|
+
h2 {font-size: 1.5em; width: 100%; text-align: center; margin: 20px; text-shadow: 2px 2px 0 #eee;}
|
5
|
+
|
6
|
+
table {
|
7
|
+
overflow:hidden;
|
8
|
+
border:1px solid #d3d3d3;
|
9
|
+
background:#fefefe;
|
10
|
+
width:98%; margin: 10px;
|
11
|
+
-moz-border-radius:5px;
|
12
|
+
-webkit-border-radius:5px;
|
13
|
+
border-radius:5px;
|
14
|
+
-moz-box-shadow: 0 0 4px rgba(0, 0, 0, 0.2);
|
15
|
+
-webkit-box-shadow: 0 0 4px rgba(0, 0, 0, 0.2);
|
16
|
+
}
|
17
|
+
|
18
|
+
th, td {padding:9px 14px 9px; text-align:center; }
|
19
|
+
|
20
|
+
th {padding-top:11px; text-shadow: 1px 1px 1px #fff; background:#e8eaeb;}
|
21
|
+
|
22
|
+
td {border-top:1px solid #e0e0e0; border-right:1px solid #e0e0e0;}
|
23
|
+
|
24
|
+
tr.odd-row td {background:#f6f6f6;}
|
25
|
+
|
26
|
+
td.first, th.first {text-align:left}
|
27
|
+
|
28
|
+
td.last {border-right:none;}
|
29
|
+
td {
|
30
|
+
background: -moz-linear-gradient(100% 25% 90deg, #fefefe, #f9f9f9);
|
31
|
+
background: -webkit-gradient(linear, 0% 0%, 0% 25%, from(#f9f9f9), to(#fefefe));
|
32
|
+
}
|
33
|
+
|
34
|
+
tr.odd-row td {
|
35
|
+
background: -moz-linear-gradient(100% 25% 90deg, #f6f6f6, #f1f1f1);
|
36
|
+
background: -webkit-gradient(linear, 0% 0%, 0% 25%, from(#f1f1f1), to(#f6f6f6));
|
37
|
+
}
|
38
|
+
|
39
|
+
th {
|
40
|
+
background: -moz-linear-gradient(100% 20% 90deg, #e8eaeb, #ededed);
|
41
|
+
background: -webkit-gradient(linear, 0% 0%, 0% 20%, from(#ededed), to(#e8eaeb));
|
42
|
+
}
|
43
|
+
|
44
|
+
tr:first-child th.first {
|
45
|
+
-moz-border-radius-topleft:5px;
|
46
|
+
-webkit-border-top-left-radius:5px;
|
47
|
+
}
|
48
|
+
|
49
|
+
tr:first-child th.last {
|
50
|
+
-moz-border-radius-topright:5px;
|
51
|
+
-webkit-border-top-right-radius:5px;
|
52
|
+
}
|
53
|
+
|
54
|
+
tr:last-child td.first {
|
55
|
+
-moz-border-radius-bottomleft:5px;
|
56
|
+
-webkit-border-bottom-left-radius:5px;
|
57
|
+
}
|
58
|
+
|
59
|
+
tr:last-child td.last {
|
60
|
+
-moz-border-radius-bottomright:5px;
|
61
|
+
-webkit-border-bottom-right-radius:5px;
|
62
|
+
}
|
63
|
+
|
64
|
+
#container {width: 900px; margin: 20px auto 0 auto;}
|
65
|
+
.header #logo {float: left; clear: both;}
|
66
|
+
#logo img {float: left; clear: left;}
|
67
|
+
#logo div {float: left; position: relative; top: 15px; left: 10px; font-size: 1.6em; letter-spacing: -2px;}
|
68
|
+
.nav {
|
69
|
+
margin: 10px 0;
|
70
|
+
float: left; clear: both;
|
71
|
+
background-color: #fafafa;
|
72
|
+
background-image: -webkit-gradient(linear, left top, left bottom, from(#efefef), to(#f2f2f2));
|
73
|
+
background-image: -webkit-linear-gradient(top, #efefef, #f2f2f2);
|
74
|
+
background-image: -moz-linear-gradient(top, #efefef, #f2f2f2);
|
75
|
+
background-image: -ms-linear-gradient(top, #efefef, #f2f2f2);
|
76
|
+
background-image: -o-linear-gradient(top, #efefef, #f2f2f2);
|
77
|
+
background-image: linear-gradient(top, #efefef, #f2f2f2);
|
78
|
+
border: 1px solid #ccc;
|
79
|
+
border-bottom: 1px solid #bbb;
|
80
|
+
-webkit-border-radius: 3px;
|
81
|
+
-moz-border-radius: 3px;
|
82
|
+
-ms-border-radius: 3px;
|
83
|
+
-o-border-radius: 3px;
|
84
|
+
border-radius: 3px;
|
85
|
+
line-height: 1;
|
86
|
+
text-align: center;
|
87
|
+
text-shadow: 0 1px 0 #eee;
|
88
|
+
width: 100%;
|
89
|
+
}
|
90
|
+
.nav li {
|
91
|
+
margin: 4px 0px;
|
92
|
+
font-size: 1em;
|
93
|
+
float: left;
|
94
|
+
background-color: #eeeeee;
|
95
|
+
background-image: -webkit-gradient(linear, left top, left bottom, from(#fafafa), to(#f7f7f7));
|
96
|
+
background-image: -webkit-linear-gradient(top, #fafafa, #f7f7f7);
|
97
|
+
background-image: -moz-linear-gradient(top, #fafafa, #f7f7f7);
|
98
|
+
background-image: -ms-linear-gradient(top, #fafafa, #f7f7f7);
|
99
|
+
background-image: -o-linear-gradient(top, #fafafa, #f7f7f7);
|
100
|
+
background-image: linear-gradient(top, #fafafa, #f7f7f7);
|
101
|
+
border: 1px solid #ccc;
|
102
|
+
border-bottom: 1px solid #bbb;
|
103
|
+
line-height: 1;
|
104
|
+
text-align: center;
|
105
|
+
text-shadow: 0 1px 0 #eee;
|
106
|
+
width: 100px;
|
107
|
+
}
|
108
|
+
.nav li:first-child {
|
109
|
+
margin-left: 4px;
|
110
|
+
-webkit-border-top-left-radius: 3px;
|
111
|
+
-moz-border-top-left-radius: 3px;
|
112
|
+
-ms-border-top-left-radius: 3px;
|
113
|
+
-o-border-top-left-radius: 3px;
|
114
|
+
border-top-left-radius: 3px;
|
115
|
+
-webkit-border-bottom-left-radius: 3px;
|
116
|
+
-moz-border-bottom-left-radius: 3px;
|
117
|
+
-ms-border-bottom-left-radius: 3px;
|
118
|
+
-o-border-bottom-left-radius: 3px;
|
119
|
+
border-bottom-left-radius: 3px;
|
120
|
+
}
|
121
|
+
.nav li:hover {
|
122
|
+
background-color: #dddddd;
|
123
|
+
background-image: -webkit-gradient(linear, left top, left bottom, from(#dddddd), to(#bbbbbb));
|
124
|
+
background-image: -webkit-linear-gradient(top, #dddddd, #bbbbbb);
|
125
|
+
background-image: -moz-linear-gradient(top, #dddddd, #bbbbbb);
|
126
|
+
background-image: -ms-linear-gradient(top, #dddddd, #bbbbbb);
|
127
|
+
background-image: -o-linear-gradient(top, #dddddd, #bbbbbb);
|
128
|
+
background-image: linear-gradient(top, #dddddd, #bbbbbb);
|
129
|
+
border: 1px solid #bbb;
|
130
|
+
border-bottom: 1px solid #999;
|
131
|
+
cursor: pointer;
|
132
|
+
text-shadow: 0 1px 0 #ddd; }
|
133
|
+
.nav li.current {
|
134
|
+
border: 1px solid #aaa;
|
135
|
+
border-bottom: 1px solid #888;
|
136
|
+
-webkit-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
|
137
|
+
-moz-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
|
138
|
+
-ms-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
|
139
|
+
-o-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
|
140
|
+
box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; }
|
141
|
+
.nav li a {text-decoration: none; color: #333; width: 100%; height: 100%; display: block; padding: 8px 0;}
|
142
|
+
.nav li.right {float: right; width: 280px; cursor: auto; padding: 4px 0 5px 0; margin-right: 4px;}
|
143
|
+
.nav li.right:hover {background-image: auto;}
|
144
|
+
.nav li.right input[type='submit'] {position: relative; top: -1px;}
|
145
|
+
|
146
|
+
#main {
|
147
|
+
margin: 10px 0;
|
148
|
+
float: left; clear: both;
|
149
|
+
background-color: #fafafa;
|
150
|
+
background-image: -webkit-gradient(linear, left top, left bottom, from(#efefef), to(#f2f2f2));
|
151
|
+
background-image: -webkit-linear-gradient(top, #efefef, #f2f2f2);
|
152
|
+
background-image: -moz-linear-gradient(top, #efefef, #f2f2f2);
|
153
|
+
background-image: -ms-linear-gradient(top, #efefef, #f2f2f2);
|
154
|
+
background-image: -o-linear-gradient(top, #efefef, #f2f2f2);
|
155
|
+
background-image: linear-gradient(top, #efefef, #f2f2f2);
|
156
|
+
border: 1px solid #ccc;
|
157
|
+
border-bottom: 1px solid #bbb;
|
158
|
+
-webkit-border-radius: 3px;
|
159
|
+
-moz-border-radius: 3px;
|
160
|
+
-ms-border-radius: 3px;
|
161
|
+
-o-border-radius: 3px;
|
162
|
+
border-radius: 3px;
|
163
|
+
line-height: 1;
|
164
|
+
text-align: left;
|
165
|
+
text-shadow: 0 1px 0 #eee;
|
166
|
+
width: 892px;
|
167
|
+
padding: 4px;
|
168
|
+
float: left; clear: both;
|
169
|
+
}
|
170
|
+
#main #page {
|
171
|
+
height: 100%; width: 892px;
|
172
|
+
background-image: -webkit-gradient(linear, left top, left bottom, from(#fafafa), to(#f7f7f7));
|
173
|
+
background-image: -webkit-linear-gradient(top, #fafafa, #f7f7f7);
|
174
|
+
background-image: -moz-linear-gradient(top, #fafafa, #f7f7f7);
|
175
|
+
background-image: -ms-linear-gradient(top, #fafafa, #f7f7f7);
|
176
|
+
background-image: -o-linear-gradient(top, #fafafa, #f7f7f7);
|
177
|
+
background-image: linear-gradient(top, #fafafa, #f7f7f7);
|
178
|
+
border: 1px solid #ccc;
|
179
|
+
border-bottom: 1px solid #bbb;
|
180
|
+
float: left; clear: both;
|
181
|
+
}
|
182
|
+
#page #left {
|
183
|
+
float: left; clear: left; width: 150px; background-color: #fafafa; border-right: 1px solid #bbb; height: 100%;
|
184
|
+
}
|
185
|
+
#page #left ul {
|
186
|
+
line-height: 1;
|
187
|
+
text-align: center;
|
188
|
+
text-shadow: 0 1px 0 #eee;
|
189
|
+
width: 100%;
|
190
|
+
}
|
191
|
+
#page #left ul li {
|
192
|
+
font-size: 1em;
|
193
|
+
float: left;
|
194
|
+
background-color: #eeeeee;
|
195
|
+
background-image: -webkit-gradient(linear, left top, left bottom, from(#fafafa), to(#f7f7f7));
|
196
|
+
background-image: -webkit-linear-gradient(top, #fafafa, #f7f7f7);
|
197
|
+
background-image: -moz-linear-gradient(top, #fafafa, #f7f7f7);
|
198
|
+
background-image: -ms-linear-gradient(top, #fafafa, #f7f7f7);
|
199
|
+
background-image: -o-linear-gradient(top, #fafafa, #f7f7f7);
|
200
|
+
background-image: linear-gradient(top, #fafafa, #f7f7f7);
|
201
|
+
border-bottom: 1px solid #bbb;
|
202
|
+
line-height: 1;
|
203
|
+
text-align: center;
|
204
|
+
text-shadow: 0 1px 0 #eee;
|
205
|
+
width: 150px;
|
206
|
+
}
|
207
|
+
#page #left ul li:hover {
|
208
|
+
background-color: #dddddd;
|
209
|
+
background-image: -webkit-gradient(linear, left top, left bottom, from(#dddddd), to(#bbbbbb));
|
210
|
+
background-image: -webkit-linear-gradient(top, #dddddd, #bbbbbb);
|
211
|
+
background-image: -moz-linear-gradient(top, #dddddd, #bbbbbb);
|
212
|
+
background-image: -ms-linear-gradient(top, #dddddd, #bbbbbb);
|
213
|
+
background-image: -o-linear-gradient(top, #dddddd, #bbbbbb);
|
214
|
+
background-image: linear-gradient(top, #dddddd, #bbbbbb);
|
215
|
+
border-bottom: 1px solid #999;
|
216
|
+
cursor: pointer;
|
217
|
+
text-shadow: 0 1px 0 #ddd; }
|
218
|
+
#page #left ul li.current {
|
219
|
+
border-bottom: 1px solid #888;
|
220
|
+
-webkit-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
|
221
|
+
-moz-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
|
222
|
+
-ms-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
|
223
|
+
-o-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
|
224
|
+
box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; }
|
225
|
+
#page #left ul li a {text-decoration: none; color: #333; width: 100%; height: 100%; display: block; padding: 8px 0;}
|
226
|
+
#page #right {
|
227
|
+
float: left; clear: right; width: 739px; height: 100%;
|
228
|
+
}
|
229
|
+
#page #graph {
|
230
|
+
width: 98%; height: 500px; margin: 0 10px;
|
231
|
+
}
|
@@ -0,0 +1,69 @@
|
|
1
|
+
<%= partial(:left) %>
|
2
|
+
|
3
|
+
<div id='right'>
|
4
|
+
<% if @query %>
|
5
|
+
<h1>Search » <%= humanize @query %> » <%= humanize @field %></h1>
|
6
|
+
<% else %>
|
7
|
+
<h1><%= humanize @field %></h1>
|
8
|
+
<% end %>
|
9
|
+
|
10
|
+
<% if @requests.empty? %>
|
11
|
+
<h2>No requests found.</h2>
|
12
|
+
<% else %>
|
13
|
+
<div id='graph'></div>
|
14
|
+
|
15
|
+
<script type='text/javascript'>
|
16
|
+
var ids = [ <%= @requests.reverse.collect{|r| "'#{r.first}'"}.join(',') %>]
|
17
|
+
|
18
|
+
$.plot($("#graph"),
|
19
|
+
[{
|
20
|
+
data: [ <%= @requests.reverse.enum_for(:each_with_index).collect {|f, i| "[#{i}, #{f.last}]"}.join(',') %> ],
|
21
|
+
label: 'requests'
|
22
|
+
}],
|
23
|
+
{
|
24
|
+
series: {
|
25
|
+
bars: { show: true, align: "center", barWidth: 0.9}
|
26
|
+
},
|
27
|
+
grid: { hoverable: true, clickable: true },
|
28
|
+
xaxis: {
|
29
|
+
autoscaleMargin: 0.05,
|
30
|
+
ticks: [ <%= @requests.reverse.enum_for(:each_with_index).collect {|f, i| "[#{i}, '#{f.first.split(' ').join('\n').gsub('/','/\n')}']"}.join(',') %> ]
|
31
|
+
},
|
32
|
+
yaxis: {
|
33
|
+
autoscaleMargin: 0.01
|
34
|
+
},
|
35
|
+
legend: {
|
36
|
+
show: false
|
37
|
+
},
|
38
|
+
colors: ["#6bc2f6", "#d18b2c", "#dba255", "#919733"]
|
39
|
+
});
|
40
|
+
|
41
|
+
var previousPoint = null;
|
42
|
+
|
43
|
+
$("#graph").bind("plothover", function (event, pos, item) {
|
44
|
+
if (item) {
|
45
|
+
if (previousPoint != item.dataIndex) {
|
46
|
+
previousPoint = item.dataIndex;
|
47
|
+
|
48
|
+
$("#tooltip").remove();
|
49
|
+
var x = item.datapoint[0].toFixed(2),
|
50
|
+
y = item.datapoint[1].toFixed(2);
|
51
|
+
|
52
|
+
showTooltip(item.pageX, item.pageY,
|
53
|
+
Math.round(y) + ' ' + item.series.label + ' for ' + item.series.xaxis.ticks[item.dataIndex].label );
|
54
|
+
}
|
55
|
+
}
|
56
|
+
else {
|
57
|
+
$("#tooltip").remove();
|
58
|
+
previousPoint = null;
|
59
|
+
}
|
60
|
+
});
|
61
|
+
|
62
|
+
$("#graph").bind("plotclick", function (event, pos, item) {
|
63
|
+
if (item) {
|
64
|
+
window.location = "/fields/<%= @field %>/" + encodeURIComponent(ids[item.dataIndex])
|
65
|
+
}
|
66
|
+
});
|
67
|
+
</script>
|
68
|
+
<% end %>
|
69
|
+
</div>
|
@@ -0,0 +1,40 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8" />
|
5
|
+
<title>AllSeeingEye</title>
|
6
|
+
<link href="<%=u '/reset.css' %>" media="screen" rel="stylesheet" type="text/css">
|
7
|
+
<link href="<%=u '/style.css' %>" media="screen" rel="stylesheet" type="text/css">
|
8
|
+
<script src="<%=u '/jquery-1.6.2.min.js' %>" type="text/javascript"></script>
|
9
|
+
<script src="<%=u '/jquery.flot.js' %>" type="text/javascript"></script>
|
10
|
+
<script src="<%=u '/jquery.equal_heights.js' %>" type="text/javascript"></script>
|
11
|
+
<script src="<%=u '/application.js' %>" type="text/javascript"></script>
|
12
|
+
</head>
|
13
|
+
<body>
|
14
|
+
<div id='container'>
|
15
|
+
<div class="header">
|
16
|
+
<div id='logo'>
|
17
|
+
<img src="<%=u '/eye.png'%>" />
|
18
|
+
<div>All Seeing Eye</div>
|
19
|
+
</div>
|
20
|
+
<ul class='nav'>
|
21
|
+
<%= tab 'Total' %>
|
22
|
+
<%= tab 'Fields' %>
|
23
|
+
<li class='right'>
|
24
|
+
<form action='/search' method='post'>
|
25
|
+
<label>Search</label>
|
26
|
+
<input name='query' type='text'>
|
27
|
+
<input type="submit" name="submit" value="Go" >
|
28
|
+
</form>
|
29
|
+
</li>
|
30
|
+
</ul>
|
31
|
+
</div>
|
32
|
+
|
33
|
+
<div id="main">
|
34
|
+
<div id="page">
|
35
|
+
<%= yield %>
|
36
|
+
</div>
|
37
|
+
</div>
|
38
|
+
</div>
|
39
|
+
</body>
|
40
|
+
</html>
|
@@ -0,0 +1,29 @@
|
|
1
|
+
<% if @field %>
|
2
|
+
<% if @id %>
|
3
|
+
<div id='left'>
|
4
|
+
<ul>
|
5
|
+
<li class=<%= current_page.split(CGI.escape(@id))[1] ? '' : 'current' %>><a href="/fields/<%= @field %>/<%= CGI.escape(@id) %>">Total</a></li>
|
6
|
+
<% (tabs - [@field]).each do |t| %>
|
7
|
+
<%= tab t, "fields/#{@field}/#{CGI.escape(@id)}" %>
|
8
|
+
<% end %>
|
9
|
+
</ul>
|
10
|
+
</div>
|
11
|
+
<% elsif @query%>
|
12
|
+
<div id='left'>
|
13
|
+
<ul>
|
14
|
+
<li class=<%= current_page.split(CGI.escape(@query))[1] ? '' : 'current' %>><a href="/search/<%= CGI.escape(@query) %>">Total</a></li>
|
15
|
+
<% tabs.each do |t| %>
|
16
|
+
<%= tab t, "search/#{CGI.escape(@query)}" %>
|
17
|
+
<% end %>
|
18
|
+
</ul>
|
19
|
+
</div>
|
20
|
+
<% else %>
|
21
|
+
<div id='left'>
|
22
|
+
<ul>
|
23
|
+
<% (tabs).each do |t| %>
|
24
|
+
<%= tab t, 'fields' %>
|
25
|
+
<% end %>
|
26
|
+
</ul>
|
27
|
+
</div>
|
28
|
+
<% end %>
|
29
|
+
<% end %>
|
@@ -0,0 +1,95 @@
|
|
1
|
+
<% if @field %>
|
2
|
+
<%= partial(:left )%>
|
3
|
+
<% elsif !@requests.empty? %>
|
4
|
+
<table cellspacing="0">
|
5
|
+
<tr>
|
6
|
+
<th></th>
|
7
|
+
<th>Today</th><th>Yesterday</th><th>This Week</th><th>All Time</th>
|
8
|
+
</tr>
|
9
|
+
|
10
|
+
<tr>
|
11
|
+
<th>Requests</th>
|
12
|
+
<td><%= AllSeeingEye::Request.count(:start => DateTime.now.beginning_of_day, :stop => DateTime.now.end_of_day) %></td>
|
13
|
+
<td><%= AllSeeingEye::Request.count(:start => DateTime.yesterday.beginning_of_day, :stop => DateTime.yesterday.end_of_day) %></td>
|
14
|
+
<td><%= AllSeeingEye::Request.count(:start => DateTime.now.beginning_of_week, :stop => DateTime.now.end_of_week) %></td>
|
15
|
+
<td><%= AllSeeingEye::Request.count %></td>
|
16
|
+
</tr>
|
17
|
+
|
18
|
+
<tr>
|
19
|
+
<th>Requests/Sec</th>
|
20
|
+
<td><%= round AllSeeingEye::Request.count(:start => DateTime.now.beginning_of_day, :stop => DateTime.now.end_of_day).to_f / (DateTime.now.to_f - DateTime.now.beginning_of_day.to_f) %></td>
|
21
|
+
<td><%= round AllSeeingEye::Request.count(:start => DateTime.yesterday.beginning_of_day, :stop => DateTime.yesterday.end_of_day).to_f / ((DateTime.now - 1.day).end_of_day.to_f - (DateTime.now - 1.day).beginning_of_day.to_f) %></td>
|
22
|
+
<td><%= round AllSeeingEye::Request.count(:start => DateTime.now.beginning_of_week, :stop => DateTime.now.end_of_week).to_f / (DateTime.now.to_f - DateTime.now.beginning_of_week.to_f) %></td>
|
23
|
+
<td><%= round AllSeeingEye::Request.count.to_f / (AllSeeingEye::Request.last.created_at.to_f - AllSeeingEye::Request.first.created_at.to_f) %></td>
|
24
|
+
</tr>
|
25
|
+
</table>
|
26
|
+
<% end %>
|
27
|
+
|
28
|
+
<% if @field %>
|
29
|
+
<div id='right'>
|
30
|
+
<% if @id %>
|
31
|
+
<h1><a href='/fields/<%= @field %>'><%= humanize @field %></a> » <%= humanize @id %></h1>
|
32
|
+
<% elsif @query %>
|
33
|
+
<h1>Search » <%= humanize @query %></h1>
|
34
|
+
<% end %>
|
35
|
+
<% else %>
|
36
|
+
<h1>Total Requests</h1>
|
37
|
+
<% end %>
|
38
|
+
|
39
|
+
<% if @counts.empty? %>
|
40
|
+
<h2>No requests found.</h2>
|
41
|
+
<% else %>
|
42
|
+
<div id='graph'></div>
|
43
|
+
|
44
|
+
<script type='text/javascript'>
|
45
|
+
$.plot($("#graph"),
|
46
|
+
[{
|
47
|
+
data: [ <%= @counts.collect{|k,v| "[#{k * 1000}, #{v}]"}.join(',') %> ],
|
48
|
+
label: 'requests'
|
49
|
+
}],
|
50
|
+
{
|
51
|
+
series: {
|
52
|
+
lines: { show: true },
|
53
|
+
points: { show: true }
|
54
|
+
},
|
55
|
+
grid: { hoverable: true },
|
56
|
+
xaxis: {
|
57
|
+
mode: "time",
|
58
|
+
timeformat: "%m/%d\n%h:%M",
|
59
|
+
autoscaleMargin: 0.01
|
60
|
+
},
|
61
|
+
yaxis: {
|
62
|
+
autoscaleMargin: 0.01
|
63
|
+
},
|
64
|
+
legend: {
|
65
|
+
show: false
|
66
|
+
},
|
67
|
+
colors: ["#6bc2f6", "#d18b2c", "#dba255", "#919733"]
|
68
|
+
});
|
69
|
+
|
70
|
+
var previousPoint = null;
|
71
|
+
|
72
|
+
$("#graph").bind("plothover", function (event, pos, item) {
|
73
|
+
if (item) {
|
74
|
+
if (previousPoint != item.dataIndex) {
|
75
|
+
previousPoint = item.dataIndex;
|
76
|
+
|
77
|
+
$("#tooltip").remove();
|
78
|
+
var x = item.datapoint[0].toFixed(2),
|
79
|
+
y = item.datapoint[1].toFixed(2),
|
80
|
+
date = new Date( );
|
81
|
+
date.setTime(x);
|
82
|
+
date = date.toUTCString();
|
83
|
+
|
84
|
+
showTooltip(item.pageX, item.pageY,
|
85
|
+
Math.round(y) + ' ' + item.series.label + ' at ' + date);
|
86
|
+
}
|
87
|
+
}
|
88
|
+
else {
|
89
|
+
$("#tooltip").remove();
|
90
|
+
previousPoint = null;
|
91
|
+
}
|
92
|
+
});
|
93
|
+
</script>
|
94
|
+
<% end %>
|
95
|
+
<% if @field %></div><% end %>
|
@@ -0,0 +1,63 @@
|
|
1
|
+
<%= partial(:left) %>
|
2
|
+
|
3
|
+
<div id='right'>
|
4
|
+
<h1><a href='/fields/<%= @field %>'><%= humanize @field %></a> » <%= humanize @id %> » <%= humanize @view %></h1>
|
5
|
+
|
6
|
+
<% if @counts.flatten.empty? %>
|
7
|
+
<h2>No requests found.</h2>
|
8
|
+
<% else %>
|
9
|
+
<div id='graph'></div>
|
10
|
+
|
11
|
+
<script type='text/javascript'>
|
12
|
+
$.plot($("#graph"),
|
13
|
+
[{
|
14
|
+
data: [ <%= @counts.enum_for(:each_with_index).collect {|f, i| "[#{i}, #{f.last}]"}.join(',') %> ],
|
15
|
+
label: 'requests'
|
16
|
+
}],
|
17
|
+
{
|
18
|
+
series: {
|
19
|
+
bars: { show: true, align: "center", barWidth: 0.9}
|
20
|
+
},
|
21
|
+
grid: { hoverable: true, clickable: true },
|
22
|
+
xaxis: {
|
23
|
+
autoscaleMargin: 0.05,
|
24
|
+
ticks: [ <%= @counts.reverse.enum_for(:each_with_index).collect {|f, i| "[#{i}, '#{f.first.split(' ').join('\n').split('?').first.gsub('/','/\n')}']"}.join(',') %> ]
|
25
|
+
},
|
26
|
+
yaxis: {
|
27
|
+
autoscaleMargin: 0.01
|
28
|
+
},
|
29
|
+
legend: {
|
30
|
+
show: false
|
31
|
+
},
|
32
|
+
colors: ["#6bc2f6", "#d18b2c", "#dba255", "#919733"]
|
33
|
+
});
|
34
|
+
|
35
|
+
var previousPoint = null;
|
36
|
+
|
37
|
+
$("#graph").bind("plothover", function (event, pos, item) {
|
38
|
+
if (item) {
|
39
|
+
if (previousPoint != item.dataIndex) {
|
40
|
+
previousPoint = item.dataIndex;
|
41
|
+
|
42
|
+
$("#tooltip").remove();
|
43
|
+
var x = item.datapoint[0].toFixed(2),
|
44
|
+
y = item.datapoint[1].toFixed(2);
|
45
|
+
|
46
|
+
showTooltip(item.pageX, item.pageY,
|
47
|
+
Math.round(y) + ' ' + item.series.label + ' for ' + item.series.xaxis.ticks[item.dataIndex].label );
|
48
|
+
}
|
49
|
+
}
|
50
|
+
else {
|
51
|
+
$("#tooltip").remove();
|
52
|
+
previousPoint = null;
|
53
|
+
}
|
54
|
+
});
|
55
|
+
|
56
|
+
$("#graph").bind("plotclick", function (event, pos, item) {
|
57
|
+
if (item) {
|
58
|
+
window.location = "/fields/<%= @field %>/" + encodeURIComponent(ids[item.dataIndex])
|
59
|
+
}
|
60
|
+
});
|
61
|
+
</script>
|
62
|
+
<% end %>
|
63
|
+
</div>
|
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'all_seeing_eye'
|
2
|
+
require 'sinatra/base'
|
3
|
+
require 'erb'
|
4
|
+
|
5
|
+
class AllSeeingEye
|
6
|
+
class Server < Sinatra::Base
|
7
|
+
dir = File.dirname(File.expand_path(__FILE__))
|
8
|
+
|
9
|
+
set :views, "#{dir}/server/views"
|
10
|
+
set :public, "#{dir}/server/public"
|
11
|
+
set :static, true
|
12
|
+
|
13
|
+
helpers do
|
14
|
+
include Rack::Utils
|
15
|
+
alias_method :h, :escape_html
|
16
|
+
|
17
|
+
def current_section
|
18
|
+
url_path request.path_info.sub('/','').split('/')[0].downcase
|
19
|
+
end
|
20
|
+
|
21
|
+
def current_page
|
22
|
+
url_path request.path_info.sub('/','')
|
23
|
+
end
|
24
|
+
|
25
|
+
def url_path(*path_parts)
|
26
|
+
[ path_parts ].join("/").squeeze('/')
|
27
|
+
end
|
28
|
+
alias_method :u, :url_path
|
29
|
+
|
30
|
+
def class_if_current(path = '')
|
31
|
+
'class="current"' if current_page.split('/').any?{|p| p == path}
|
32
|
+
end
|
33
|
+
|
34
|
+
def tab(name, prefix = nil)
|
35
|
+
dname = name.to_s.downcase
|
36
|
+
path = url_path(dname)
|
37
|
+
"<li #{class_if_current(path)}><a href='/#{prefix.nil? ? '' : "#{prefix}/"}#{path}'>#{humanize name}</a></li>"
|
38
|
+
end
|
39
|
+
|
40
|
+
def round(float, n = 2)
|
41
|
+
(float * (10.0 ** n)).round * (10.0 ** (-n))
|
42
|
+
end
|
43
|
+
|
44
|
+
def humanize(string)
|
45
|
+
string.split('_').collect(&:capitalize).join(' ')
|
46
|
+
end
|
47
|
+
|
48
|
+
def partial?
|
49
|
+
@partial
|
50
|
+
end
|
51
|
+
|
52
|
+
def partial(template, local_vars = {})
|
53
|
+
@partial = true
|
54
|
+
erb(template.to_sym, {:layout => false}, local_vars)
|
55
|
+
ensure
|
56
|
+
@partial = false
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
def show(page, layout = true)
|
62
|
+
response["Cache-Control"] = "max-age=0, private, must-revalidate"
|
63
|
+
erb page.to_sym, {:layout => layout}
|
64
|
+
end
|
65
|
+
|
66
|
+
get "/?" do
|
67
|
+
redirect url_path(:total)
|
68
|
+
end
|
69
|
+
|
70
|
+
get '/total' do
|
71
|
+
@requests = AllSeeingEye::Request.search("one month ago to now")
|
72
|
+
@counts = AllSeeingEye::Request.conglomerate(@requests)
|
73
|
+
show :total
|
74
|
+
end
|
75
|
+
|
76
|
+
post '/search' do
|
77
|
+
redirect "/search/#{params[:query]}"
|
78
|
+
end
|
79
|
+
|
80
|
+
get '/search/:id' do
|
81
|
+
@field = 'total'
|
82
|
+
@query = params[:id]
|
83
|
+
@requests = AllSeeingEye::Request.search(@query)
|
84
|
+
@counts = AllSeeingEye::Request.conglomerate(@requests)
|
85
|
+
show :total
|
86
|
+
end
|
87
|
+
|
88
|
+
get "/fields" do
|
89
|
+
redirect "/fields/#{AllSeeingEye::Request.field_keys.first}"
|
90
|
+
end
|
91
|
+
|
92
|
+
AllSeeingEye::Request.field_keys.each do |field|
|
93
|
+
get "/fields/#{field}" do
|
94
|
+
@field = field
|
95
|
+
@requests = AllSeeingEye::Request.count_by_field(@field)
|
96
|
+
show :field
|
97
|
+
end
|
98
|
+
|
99
|
+
get "/search/:id/#{field}" do
|
100
|
+
@field = field
|
101
|
+
@query = params[:id]
|
102
|
+
@requests = AllSeeingEye::Request.search(@query)
|
103
|
+
counts = Hash.new(0)
|
104
|
+
@requests.each {|r| next if r.send(@field.to_sym).nil?; counts[r.send(@field.to_sym)] += 1}
|
105
|
+
@requests = counts.sort {|a, b| b.last <=> a.last}
|
106
|
+
show :field
|
107
|
+
end
|
108
|
+
|
109
|
+
(AllSeeingEye::Request.field_keys - [field]).each do |f|
|
110
|
+
get %r{/fields/#{field}/(.*?)/#{f}$} do
|
111
|
+
@field = field
|
112
|
+
@id = params[:captures].first
|
113
|
+
@view = f
|
114
|
+
@requests = AllSeeingEye::Request.find_by_field(@field, :value => @id)
|
115
|
+
@counts = Hash.new(0)
|
116
|
+
@requests.each {|r| next if r.send(@view.to_sym).nil?; @counts[r.send(@view.to_sym)] += 1}
|
117
|
+
@counts = @counts.sort {|a, b| b.last <=> a.last}
|
118
|
+
show :view
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
get %r{/fields/#{field}/(.*)$} do
|
123
|
+
@field = field
|
124
|
+
@id = params[:captures].first
|
125
|
+
@requests = AllSeeingEye::Request.find_by_field(@field, :value => @id)
|
126
|
+
@counts = AllSeeingEye::Request.conglomerate(@requests)
|
127
|
+
show :total
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def tabs
|
132
|
+
@tabs ||= AllSeeingEye::Request.field_keys
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|