Add 'apps/arv-web/' from commit 'f9732ad8460d013c2f28363655d0d1b91894dca5'
[arvados.git] / apps / workbench / app / views / jobs / _show_log.html.erb
1 <% if !@object.log %>
2
3 <div id="log_graph_div"
4      class="arv-log-event-listener"
5      data-object-uuid="<%= @object.uuid %>"></div>
6
7 <div id="event_log_div"
8      class="arv-log-event-listener arv-log-event-handler-append-logs arv-job-log-window"
9      data-object-uuid="<%= @object.uuid %>"
10      ></div>
11
12 <%# Applying a long throttle suppresses the auto-refresh of this
13     partial that would normally be triggered by arv-log-event. %>
14 <div class="arv-log-refresh-control"
15      data-load-throttle="86486400000" <%# 1001 nights %>
16      ></div>
17
18 <% else %>
19
20 <script>
21 (function() {
22 var pagesize = 1000;
23 var logViewer = new List('log-viewer', {
24   valueNames: [ 'id', 'timestamp', 'taskid', 'message', 'type'],
25   page: pagesize
26 });
27
28 logViewer.page_offset = 0;
29 logViewer.on("updated", function() { updatePaging(".log-viewer-paging", logViewer, pagesize) } );
30 $(".log-viewer-page-up").on("click", function() { prevPage(logViewer, pagesize, ".log-viewer-paging"); return false; });
31 $(".log-viewer-page-down").on("click", function() { nextPage(logViewer, pagesize, ".log-viewer-paging"); return false; });
32
33 var taskState = newTaskState();
34
35 var makeFilter = function() {
36   var pass = [];
37   $(".toggle-filter, .radio-filter").each(function(i, e) {
38     if (e.checked) {
39       pass.push(e.id.substr(5));
40     }
41   });
42
43   return (function(item) {
44     var v = false;
45     if (item.values().taskid !== "") {
46       for (a in pass) {
47         if (pass[a] == "all-tasks") { v = true; }
48         else if (pass[a] == "successful-tasks" && taskState[item.values().taskid].outcome == "success") { v = true; }
49         else if (pass[a] == "failed-tasks" && taskState[item.values().taskid].outcome == "failure") { v = true; }
50       }
51     } else {
52       v = true;
53     }
54     for (a in pass) {
55       if (pass[a] == item.values().type) { return v; }
56     }
57     return false;
58   });
59 }
60
61 <% if @object.log and !@object.log.empty? %>
62   <% logcollection = Collection.find @object.log %>
63   <% if logcollection %>
64     log_size = <%= logcollection.files[0][2] %>
65     log_maxbytes = <%= Rails.configuration.log_viewer_max_bytes %>;
66     logcollection_url = '<%=j url_for logcollection %>/<%=j logcollection.files[0][1] %>';
67     $("#log-viewer-download-url").attr('href', logcollection_url);
68     $("#log-viewer-download-pane").show();
69     if (log_size > log_maxbytes) {
70       range_header = { 'Range': 'bytes=0-' + log_maxbytes };
71     } else {
72       range_header = null;
73     }
74     $.ajax(logcollection_url, { headers: range_header }).
75         done(function(data, status, jqxhr) {
76             logViewer.filter();
77             addToLogViewer(logViewer, data.split("\n"), taskState);
78             logViewer.filter(makeFilter());
79             content_range_hdr = jqxhr.getResponseHeader('Content-Range');
80             var v = content_range_hdr && content_range_hdr.match(/bytes \d+-(\d+)\/(.+)/);
81             short_log = v && (v[2] == '*' || parseInt(v[1]) + 1 < v[2]);
82             if (jqxhr.status == 206 && short_log) {
83               $("#log-viewer-overview").html(
84                 '<p>Showing only ' + data.length + ' bytes of this log.' +
85                 ' Timing information is unavailable since' +
86                 ' the full log was not retrieved.</p>'
87               );
88             } else {
89               generateJobOverview("#log-viewer-overview", logViewer, taskState);
90             }
91             $("#log-viewer .spinner").detach();
92         }).
93         fail(function(jqxhr, status, error) {
94             $("#log-viewer .spinner").detach();
95         });
96   <% end %>
97 <% else %>
98   <%# Live log loading not implemented yet. %>
99 <% end %>
100
101 $(".toggle-filter, .radio-filter").on("change", function() {
102   logViewer.filter(makeFilter());
103 });
104
105 $("#filter-all").on("click", function() {
106   $(".toggle-filter").each(function(i, f) { f.checked = true; });
107   logViewer.filter(makeFilter());
108 });
109
110 $("#filter-none").on("click", function() {
111   $(".toggle-filter").each(function(i, f) { f.checked = false; console.log(f); });
112   logViewer.filter(makeFilter());
113 });
114
115 $("#sort-by-time").on("change", function() {
116   logViewer.sort("id", {sortFunction: sortById});
117 });
118
119 $("#sort-by-task").on("change", function() {
120   logViewer.sort("taskid", {sortFunction: sortByTask});
121 });
122
123 $("#sort-by-node").on("change", function() {
124   logViewer.sort("node", {sortFunction: sortByNode});
125 });
126
127 $("#set-show-failed-only").on("click", function() {
128   $("#sort-by-task").prop("checked", true);
129   $("#show-failed-tasks").prop("checked", true);
130   $("#show-crunch").prop("checked", false);
131   $("#show-task-dispatch").prop("checked", true);
132   $("#show-script-print").prop("checked", true);
133   $("#show-crunchstat").prop("checked", false);
134   logViewer.filter(makeFilter());
135   logViewer.sort("taskid", {sortFunction: sortByTask});
136 });
137
138 })();
139
140 </script>
141
142 <div id="log-viewer">
143
144   <h3>Summary</h3>
145   <p id="log-viewer-overview">
146     <% if !logcollection %>
147       The collection containing the job log was not found.
148     <% end %>
149   </p>
150
151   <p id="log-viewer-download-pane" style="display:none">
152     <a id="log-viewer-download-url" href="">Download the full log</a>
153   </p>
154
155   <div class="h3">Log
156
157     <span class="pull-right">
158       <% if @object.andand.tasks_summary.andand[:failed] and @object.tasks_summary[:failed] > 0 %>
159         <button id="set-show-failed-only" class="btn btn-danger">
160           Show failed task diagnostics only
161         </button>
162       <% end %>
163
164       <button id="filter-all" class="btn">
165         Select all
166       </button>
167       <button id="filter-none" class="btn">
168         Select none
169       </button>
170     </span>
171   </div>
172
173   <input class="search pull-right" style="margin-top: 1em" placeholder="Search" />
174
175   <div>
176     <div class="radio-inline log-viewer-button" style="margin-left: 10px">
177       <label><input id="sort-by-time" type="radio" name="sort-radio" checked> Sort by time</label>
178     </div>
179     <div class="radio-inline log-viewer-button">
180       <label><input id="sort-by-node" type="radio" name="sort-radio" > Sort by node</label>
181     </div>
182
183     <div class="radio-inline log-viewer-button">
184       <label><input id="sort-by-task" type="radio" name="sort-radio" > Sort by task</label>
185     </div>
186   </div>
187
188   <div>
189     <div class="radio-inline log-viewer-button" style="margin-left: 10px">
190       <label><input id="show-all-tasks" type="radio" name="show-tasks-group" checked="true" class="radio-filter"> Show all tasks</label>
191     </div>
192     <div class="radio-inline log-viewer-button">
193       <label><input id="show-successful-tasks" type="radio" name="show-tasks-group" class="radio-filter"> Only successful tasks</label>
194     </div>
195     <div class="radio-inline log-viewer-button">
196       <label><input id="show-failed-tasks" type="radio" name="show-tasks-group" class="radio-filter"> Only failed tasks</label>
197     </div>
198   </div>
199
200   <div>
201     <div class="checkbox-inline log-viewer-button" style="margin-left: 10px">
202       <label><input id="show-crunch" type="checkbox" checked="true" class="toggle-filter"> Show crunch diagnostics</label>
203     </div>
204     <div class="checkbox-inline log-viewer-button">
205       <label><input id="show-task-dispatch" type="checkbox" checked="true" class="toggle-filter"> Show task dispatch</label>
206     </div>
207     <div class="checkbox-inline log-viewer-button">
208       <label><input id="show-task-print" type="checkbox" checked="true" class="toggle-filter"> Show task diagnostics</label>
209     </div>
210     <div class="checkbox-inline log-viewer-button">
211       <label><input id="show-crunchstat" type="checkbox" checked="true" class="toggle-filter"> Show compute usage</label>
212     </div>
213
214   </div>
215
216   <div class="smart-scroll" data-smart-scroll-padding-bottom="50" style="margin-bottom: 0px">
217     <table class="log-viewer-table">
218       <thead>
219         <tr>
220           <th class="id" data-sort="id"></th>
221           <th class="timestamp" data-sort="timestamp">Timestamp</th>
222           <th class="node"  data-sort="node">Node</th>
223           <th class="slot"  data-sort="slot">Slot</th>
224           <th class="type" data-sort="type">Log type</th>
225           <th class="taskid"  data-sort="taskid">Task</th>
226           <th class="message" data-sort="message">Message</th>
227         </tr>
228       </thead>
229       <tbody class="list">
230         <tr>
231           <td class="id"></td>
232           <td class="timestamp"></td>
233           <td class="node"></td>
234           <td class="slot"></td>
235           <td class="type"></td>
236           <td class="taskid"></td>
237           <td class="message"></td>
238         </tr>
239       </tbody>
240     </table>
241
242     <% if @object.log and logcollection %>
243       <div class="spinner spinner-32px"></div>
244     <% end %>
245
246   </div>
247
248   <div class="log-viewer-paging-div" style="margin-bottom: -15px">
249     <a href="#" class="log-viewer-page-up"><span class='glyphicon glyphicon-arrow-up'></span></a>
250     <span class="log-viewer-paging"></span>
251     <a href="#" class="log-viewer-page-down"><span class='glyphicon glyphicon-arrow-down'></span></a>
252   </div>
253
254 </div>
255
256 <% end %>