wackamole 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -0
- data/bin/setup_indexes +44 -0
- data/bin/wackamole +8 -6
- data/config.ru +18 -0
- data/lib/app.rb +8 -5
- data/lib/controllers/dashboard.rb +13 -1
- data/lib/controllers/features.rb +4 -0
- data/lib/controllers/logs.rb +14 -5
- data/lib/controllers/mission.rb +19 -12
- data/lib/controllers/users.rb +7 -0
- data/lib/helpers/dashboard_helper.rb +7 -7
- data/lib/helpers/logs_helper.rb +29 -12
- data/lib/helpers/mission_helper.rb +21 -7
- data/lib/wackamole.rb +1 -1
- data/lib/wackamole/models/control.rb +45 -22
- data/lib/wackamole/models/log.rb +6 -4
- data/lib/wackamole/models/mission.rb +44 -132
- data/lib/wackamole/models/mole_info.rb +21 -15
- data/lib/wackamole/models/search_filter.rb +25 -11
- data/public/images/browsers_sprite.png +0 -0
- data/public/images/fault_small.png +0 -0
- data/public/images/perf_small.png +0 -0
- data/public/stylesheets/wackamole.css +135 -111
- data/spec/models/log_spec.rb +4 -4
- data/spec/models/mission_spec.rb +13 -192
- data/spec/models/search_filter_spec.rb +37 -9
- data/views/dashboard/_report.erb +2 -2
- data/views/dashboard/index.erb +2 -0
- data/views/features/index.erb +3 -1
- data/views/layout.erb +7 -7
- data/views/logs/_rows.erb +4 -3
- data/views/logs/index.erb +3 -1
- data/views/logs/show.erb +4 -8
- data/views/mission/_report.erb +66 -40
- data/views/mission/index.erb +1 -3
- data/views/mission/refresh_js.erb +5 -2
- data/views/mission/trash.txt +50 -0
- data/views/shared/_filter.erb +8 -9
- data/views/shared/_search.erb +2 -2
- data/views/users/index.erb +3 -1
- metadata +18 -2
@@ -20,6 +20,22 @@ describe Wackamole::SearchFilter do
|
|
20
20
|
@filter.reset!
|
21
21
|
check_filter( @filter, "today", "All", "", -1)
|
22
22
|
end
|
23
|
+
|
24
|
+
it "should retrieve the correct feature context" do
|
25
|
+
@filter.context_for( {'ctx' => "/blee/fred" } ).should == "/blee/fred"
|
26
|
+
@filter.context_for( {'ctl' => "blee", 'act' => "fred" } ).should == "blee#fred"
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should retrieve the correct start date" do
|
30
|
+
@filter.from_date_id.should_not be_nil
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should map id to type correctly" do
|
34
|
+
types = %w( Feature Perf Fault )
|
35
|
+
[0,1,2].each do |t|
|
36
|
+
@filter.send( :to_filter_type, t ).should == types[t]
|
37
|
+
end
|
38
|
+
end
|
23
39
|
|
24
40
|
describe "series" do
|
25
41
|
it "should generate the correct time_ids" do
|
@@ -59,7 +75,7 @@ describe Wackamole::SearchFilter do
|
|
59
75
|
conds.should have(2).items
|
60
76
|
conds.key?( :did ).should == true
|
61
77
|
conds[:did].should == { "$gte" => @now.to_date_id.to_s }
|
62
|
-
conds[
|
78
|
+
conds['bro.name'].should == "Safari"
|
63
79
|
end
|
64
80
|
|
65
81
|
it "should include mole type is specfied" do
|
@@ -70,7 +86,7 @@ describe Wackamole::SearchFilter do
|
|
70
86
|
conds.should have(3).items
|
71
87
|
conds.key?( :did ).should == true
|
72
88
|
conds[:did].should == { "$gte" => @now.to_date_id.to_s }
|
73
|
-
conds[
|
89
|
+
conds['bro.name'].should == "Safari"
|
74
90
|
conds[:typ].should == Rackamole.feature
|
75
91
|
end
|
76
92
|
|
@@ -91,6 +107,18 @@ describe Wackamole::SearchFilter do
|
|
91
107
|
Wackamole::Control.db( "mole_fred_test_mdb" )
|
92
108
|
end
|
93
109
|
|
110
|
+
it "should retrieve features correctly" do
|
111
|
+
features = @filter.features
|
112
|
+
features.should have(11).items
|
113
|
+
count = 0
|
114
|
+
features.each do |f|
|
115
|
+
f.should have(2).items
|
116
|
+
f.first.should == "All" if count == 0
|
117
|
+
f.first.should == "feature_#{count-1}" if count > 0
|
118
|
+
count += 1
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
94
122
|
it "should include user if specified" do
|
95
123
|
@filter.search_terms = "user:blee_0@fred.test"
|
96
124
|
conds = @filter.to_conds
|
@@ -102,19 +130,19 @@ describe Wackamole::SearchFilter do
|
|
102
130
|
end
|
103
131
|
|
104
132
|
it "should include an adoc regexp if specified" do
|
105
|
-
@filter.search_terms = "
|
106
|
-
conds = @filter.to_conds
|
133
|
+
@filter.search_terms = "host:blee"
|
134
|
+
conds = @filter.to_conds
|
107
135
|
conds.should have(2).items
|
108
|
-
conds[
|
109
|
-
conds[
|
136
|
+
conds[:hos].should_not be_nil
|
137
|
+
conds[:hos].should == /blee/
|
110
138
|
end
|
111
139
|
|
112
140
|
it "should include an adoc regexp if specified" do
|
113
|
-
@filter.search_terms = "
|
141
|
+
@filter.search_terms = "browser:name:duh"
|
114
142
|
conds = @filter.to_conds
|
115
143
|
conds.should have(2).items
|
116
|
-
conds['
|
117
|
-
conds['
|
144
|
+
conds['bro.name'].should_not be_nil
|
145
|
+
conds['bro.name'].should == /duh/
|
118
146
|
end
|
119
147
|
|
120
148
|
it "should raise an exception is search exp cannot be parsed" do
|
data/views/dashboard/_report.erb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
<div class="section" id="summary">
|
2
|
-
<p class="title">
|
2
|
+
<p class="title">this hour</p>
|
3
3
|
<ul id="summary">
|
4
4
|
<li>
|
5
5
|
<p class="status">Users</p>
|
@@ -20,7 +20,7 @@
|
|
20
20
|
</div>
|
21
21
|
|
22
22
|
<div class="section" id="activity">
|
23
|
-
<p class="title">
|
23
|
+
<p class="title">day summary</p>
|
24
24
|
<ul class="section">
|
25
25
|
<li>
|
26
26
|
<p id="faults">Faults</p>
|
data/views/dashboard/index.erb
CHANGED
data/views/features/index.erb
CHANGED
data/views/layout.erb
CHANGED
@@ -6,28 +6,28 @@
|
|
6
6
|
<link rel="icon" href="/images/small_logo.png" type="image/x-icon"/>
|
7
7
|
<link rel="shortcut icon" href="/images/small_logo.png" type="image/x-icon"/>
|
8
8
|
<%= stylesheets %w[wackamole] %>
|
9
|
-
<%= javascripts %w[jquery_min jquery_ui_min
|
9
|
+
<%= javascripts %w[jquery_min jquery_ui_min] %>
|
10
10
|
</head>
|
11
11
|
|
12
12
|
<body id="body">
|
13
13
|
<div id="overall">
|
14
|
-
<div id="logo" style="margin-bottom:
|
15
|
-
<%= link_to image_tag( 'wackamole_logo.png', :border => 0 ), '/
|
14
|
+
<div id="logo" style="margin-bottom:5px">
|
15
|
+
<%= link_to image_tag( 'wackamole_logo.png', :border => 0 ), '/' %>
|
16
16
|
</div>
|
17
17
|
<div id="app_info">
|
18
18
|
<% if @app_info %>
|
19
19
|
<ul>
|
20
|
-
<li>&
|
20
|
+
<li>«<span><%=@app_info[:app_name]%></span>»</li>
|
21
21
|
<li id="env"><%=@app_info[:stage]%></li>
|
22
22
|
<ul>
|
23
23
|
<% end %>
|
24
|
-
<p id="timestamp"><%=partial :'shared/timestamp'%></p>
|
24
|
+
<p><span id="timestamp"><%=partial :'shared/timestamp'%></span></p>
|
25
25
|
</div>
|
26
26
|
<div id="main">
|
27
27
|
<div class="flash"></div>
|
28
28
|
<% if @app_info %>
|
29
|
-
<div id='navigation'>
|
30
|
-
<%=link_to "mission control", "/
|
29
|
+
<div id='navigation' class='corners'>
|
30
|
+
<%=link_to "mission control", "/" , :class => "site_link land" %> •
|
31
31
|
<%=link_to "dashboard" , "/dashboard/#{@app_info[:app_name]}/#{@app_info[:stage]}", :class => "site_link dash" %> •
|
32
32
|
<%=link_to "logs" , "/logs/1" , :class => "site_link logs" %> •
|
33
33
|
<%=link_to "features" , "/features/1" , :class => "site_link features" %> •
|
data/views/logs/_rows.erb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
<%= page_entries_info @logs, :entry_name => 'log' %>
|
3
3
|
</div>
|
4
4
|
|
5
|
+
<% users={}; contexts={} %>
|
5
6
|
<div id="content">
|
6
7
|
<table class="logs">
|
7
8
|
<thead>
|
@@ -17,14 +18,14 @@
|
|
17
18
|
<tbody>
|
18
19
|
<% count=0;@logs.each do |log| %>
|
19
20
|
<tr class="<%=row_class_for log['typ'] %>" href="<%="/logs/#{log['_id']}/show"%>" rel='#details'>
|
20
|
-
<td><%=context_for log['fid'] %></td>
|
21
|
+
<td><%=context_for( contexts, log['fid']) %></td>
|
21
22
|
<td><%=log['met']%></td>
|
22
|
-
<td><%=truncate( user_name_for( log['uid'] ), 30 )%></td>
|
23
|
+
<td><%=truncate( user_name_for( users, log['uid'] ), 30 )%></td>
|
23
24
|
<td><%=log['ip']%></td>
|
24
25
|
<td><%=format_host( log['hos'] )%></td>
|
25
26
|
<td><%=timestamp_for log %></td>
|
26
27
|
<td align="right"><%=request_time( log['rti'] )%></td>
|
27
|
-
<td align="right"
|
28
|
+
<td align="right"><div class="browser <%=browser_class( log['bro'])%>"></div></td>
|
28
29
|
</tr>
|
29
30
|
<% count+=1;end %>
|
30
31
|
</body>
|
data/views/logs/index.erb
CHANGED
data/views/logs/show.erb
CHANGED
@@ -1,11 +1,7 @@
|
|
1
1
|
<p id="info">
|
2
|
-
<%=image_tag mole_type_icon( @log['typ'] ), :border => 0 %>
|
3
|
-
<
|
4
|
-
|
5
|
-
</p>
|
6
|
-
<p class="title" id="feature">
|
7
|
-
<%=context_for @log['fid'] %>
|
8
|
-
</p>
|
2
|
+
<%=image_tag mole_type_icon( @log['typ'] ), :border => 0, :class => "info", :size => "35x35" %>
|
3
|
+
<span id="type"><%=human_type @log['typ'] %></span>
|
4
|
+
<span id="feature"><%=context_for( {}, @log['fid'] ) %></span>
|
9
5
|
</p>
|
10
6
|
|
11
7
|
<div id="info">
|
@@ -19,7 +15,7 @@
|
|
19
15
|
<% end %>
|
20
16
|
<tr>
|
21
17
|
<td class="label">User</td>
|
22
|
-
<td><%=user_name_for @log['uid'] %></td>
|
18
|
+
<td><%=user_name_for( {}, @log['uid'] ) %></td>
|
23
19
|
</tr>
|
24
20
|
<tr>
|
25
21
|
<td class="label">Method</td>
|
data/views/mission/_report.erb
CHANGED
@@ -1,49 +1,75 @@
|
|
1
|
-
|
1
|
+
<style>
|
2
|
+
table#mission {
|
3
|
+
width: 100%;
|
4
|
+
border: 1;
|
5
|
+
text-align: left;
|
6
|
+
min-height: 500px;
|
7
|
+
}
|
8
|
+
table#mission thead tr {
|
9
|
+
font-size: 1.2em;
|
10
|
+
color: #808080;
|
11
|
+
}
|
12
|
+
table#mission tr.div {
|
13
|
+
border-bottom: 1px #c1c1c1 solid;
|
14
|
+
}
|
15
|
+
</style>
|
16
|
+
|
17
|
+
<% applications = extract_applications( @pulse ) %>
|
18
|
+
<% if applications.count == 0 %>
|
2
19
|
<div class="doh">
|
3
20
|
<p>Unable to find a Rackamole MongoDb database on this connection <%=Wackamole::Control.connection.host%>:<%=Wackamole::Control.connection.port%>.</p>
|
4
21
|
<p>Make sure you moled database follows this naming convention</p>
|
5
22
|
<p>mole_{<i>application name in lower case</i>}_{<i>environment</i>}_mdb</p>
|
6
23
|
</div>
|
7
24
|
<% else %>
|
8
|
-
|
9
|
-
<
|
10
|
-
<
|
11
|
-
|
12
|
-
<
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
<
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
25
|
+
<table class="logs" id="mission">
|
26
|
+
<thead>
|
27
|
+
<tr>
|
28
|
+
<th width="25%">application</th>
|
29
|
+
<th width="10%">environment</th>
|
30
|
+
<th width="20%">to date</th>
|
31
|
+
<th width="20%">today</th>
|
32
|
+
<th width="20%">last tick</th>
|
33
|
+
</tr>
|
34
|
+
</thead>
|
35
|
+
<tbody>
|
36
|
+
<% applications.each_pair do |app_name, envs| %>
|
37
|
+
<% envs.each do |env| %>
|
38
|
+
<tr class="div">
|
39
|
+
<td valign="top"><%= link_to app_name, "/dashboard/#{app_name}/#{env}", :class => 'site_link' %></td>
|
40
|
+
<td valign="top"><%= env %></td>
|
41
|
+
<% %w(to_date today last_tick).each do |period| %>
|
42
|
+
<% info = @pulse[period.to_sym][app_name][env] %>
|
43
|
+
<td>
|
44
|
+
<table border="0" width="100%">
|
45
|
+
<tbody>
|
46
|
+
<% info.each_pair do |type, count| %>
|
47
|
+
<tr>
|
48
|
+
<% clazz = ( (count > 0 and %w(last_tick today).include?(period)) ? assign_class( type, count ) : nil) %>
|
49
|
+
<td width="25px">
|
50
|
+
<% if( %w(last_tick today).include?( period ) and count > 0 ) %>
|
51
|
+
<%= link_to Wackamole::Mission.to_type_name(type), "/dashboard/logs/#{app_name}/#{env}/#{type}", :class => "site_link" %>:
|
52
|
+
<% else %>
|
53
|
+
<%=Wackamole::Mission.to_type_name(type)%>:
|
54
|
+
<% end %>
|
55
|
+
</td>
|
56
|
+
<td align='right'>
|
57
|
+
<span class="<%= (clazz and count > 0 ? "#{period}_#{clazz}" : '') %>">
|
58
|
+
<%= format_number(count) %>
|
59
|
+
</span>
|
60
|
+
</td>
|
61
|
+
<!-- < if period == 'last_tick' %>
|
62
|
+
<td width="5px" class="<=clazz%>"> </td>
|
63
|
+
< end %> -->
|
64
|
+
</tr>
|
65
|
+
<% end %>
|
66
|
+
</tbody>
|
67
|
+
</table>
|
68
|
+
</td>
|
42
69
|
<% end %>
|
43
|
-
|
44
|
-
|
45
|
-
</div>
|
70
|
+
</tr>
|
71
|
+
<% end %>
|
46
72
|
<% end %>
|
47
|
-
</
|
48
|
-
|
73
|
+
</tbody>
|
74
|
+
</table>
|
49
75
|
<% end %>
|
data/views/mission/index.erb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
-
$('
|
1
|
+
$('span#timestamp').html( "<%=escape_javascript(partial(:'shared/timestamp'))%>" );
|
2
|
+
$("span#timestamp").effect( 'pulsate', { times:1 }, 500 );
|
2
3
|
|
3
|
-
$('div#
|
4
|
+
$('div#mission').html( "<%=escape_javascript(partial(:'mission/report'))%>" );
|
5
|
+
|
6
|
+
$("span.last_tick_fault" ).effect( 'shake', { times: 3, distance: 5, direction: 'left' }, 300 );
|
@@ -0,0 +1,50 @@
|
|
1
|
+
<% applications = extract_applications( @pulse ) %>
|
2
|
+
<% if applications.count == 0 %>
|
3
|
+
<div class="doh">
|
4
|
+
<p>Unable to find a Rackamole MongoDb database on this connection <%=Wackamole::Control.connection.host%>:<%=Wackamole::Control.connection.port%>.</p>
|
5
|
+
<p>Make sure you moled database follows this naming convention</p>
|
6
|
+
<p>mole_{<i>application name in lower case</i>}_{<i>environment</i>}_mdb</p>
|
7
|
+
</div>
|
8
|
+
<% else %>
|
9
|
+
<% @.each do |report| %>
|
10
|
+
<div class="mission">
|
11
|
+
<p class="app_name"><%= report['app'] %></p>
|
12
|
+
<% report['envs'].keys.sort.each do |env| %>
|
13
|
+
<div class="environment">
|
14
|
+
<div class="env">
|
15
|
+
<%= link_to env, "/dashboard/#{report['app']}/#{env}", :class => 'site_link app_link' %>
|
16
|
+
</div>
|
17
|
+
<div class="details">
|
18
|
+
<table border='0' width="100%">
|
19
|
+
<% report['envs'][env].each do |type, count| %>
|
20
|
+
<% diff = compute_diff( report['app'], env, type, count )%>
|
21
|
+
<tr>
|
22
|
+
<td class="<%=assign_class( type, count, diff )%>" align="left">
|
23
|
+
<%=type.capitalize %>
|
24
|
+
</td>
|
25
|
+
<td>
|
26
|
+
<%=count%>
|
27
|
+
</td>
|
28
|
+
<td>
|
29
|
+
‹<%= delta?( diff ) %>›
|
30
|
+
</td>
|
31
|
+
<% if type != 'features' and count > 0%>
|
32
|
+
<td align='right'>
|
33
|
+
<%= link_to_remote 'fixed',
|
34
|
+
"/mission/fixed/#{report['app']}/#{env}/#{type}",
|
35
|
+
:class => "fixed" %>
|
36
|
+
</td>
|
37
|
+
<% else %>
|
38
|
+
<td>
|
39
|
+
<p style="width:30px"></p>
|
40
|
+
</td>
|
41
|
+
<% end %>
|
42
|
+
</tr>
|
43
|
+
<% end %>
|
44
|
+
</table>
|
45
|
+
</div>
|
46
|
+
</div>
|
47
|
+
<% end %>
|
48
|
+
</div>
|
49
|
+
<% end %>
|
50
|
+
<% end %>
|
data/views/shared/_filter.erb
CHANGED
@@ -1,13 +1,5 @@
|
|
1
|
-
<div id="filters">
|
1
|
+
<div id="filters" class="corners">
|
2
2
|
<form id="filter_form">
|
3
|
-
<fieldset id="submit">
|
4
|
-
<label>
|
5
|
-
|
6
|
-
<input type="submit" name="commit" value="Filter"/>
|
7
|
-
<%= image_tag 'loading.gif', :border => '0', :size => '24x24', :id => 'loading' %>
|
8
|
-
</label>
|
9
|
-
</fieldset>
|
10
|
-
|
11
3
|
<fieldset class="inline">
|
12
4
|
<label for="time_frame">
|
13
5
|
Time range:
|
@@ -43,6 +35,13 @@
|
|
43
35
|
</select>
|
44
36
|
</label>
|
45
37
|
</fieldset>
|
38
|
+
<fieldset id="submit">
|
39
|
+
<label>
|
40
|
+
|
41
|
+
<input type="submit" name="commit" value="Filter"/>
|
42
|
+
<%= image_tag 'loading.gif', :border => '0', :size => '24x24', :id => 'loading' %>
|
43
|
+
</label>
|
44
|
+
</fieldset>
|
46
45
|
</form>
|
47
46
|
</div>
|
48
47
|
|
data/views/shared/_search.erb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
<div id="search">
|
2
2
|
<form id="search_form">
|
3
|
-
<input id="search_term" class="search" type="text" size="
|
4
|
-
<%= image_tag 'loading.gif', :border => 0, :size => "
|
3
|
+
<input id="search_term" class="search" type="text" size="50" name="search_filter[search_terms]"/>
|
4
|
+
<%= image_tag 'loading.gif', :border => 0, :size => "20x20", :id => "search_loader" %>
|
5
5
|
<input type="submit" value="Search" style="display: none;" name="commit"/>
|
6
6
|
</form>
|
7
7
|
</div>
|