2883: Added filtering for crunchstat, slurm log lines.
[arvados.git] / apps / workbench / app / views / jobs / _show_log.html.erb
1 <script>
2
3 function addToLogViewer(logViewer, lines) {
4   var re = /((\d\d\d\d)-(\d\d)-(\d\d))_((\d\d):(\d\d):(\d\d)) ([a-z0-9]{5}-[a-z0-9]{5}-[a-z0-9]{15}) (\d+) (\d+)? (.*)/;
5   for (var a in lines) {
6     var v = lines[a].match(re);
7     if (v != null) {
8
9     var ts = new Date(Date.UTC(v[2], v[3], v[4], v[6], v[7], v[8]));
10
11     v11 = v[11];
12     if (typeof v[11] === 'undefined') {
13       v11 = '&nbsp;';
14     }
15
16   var message = v[12];
17   var type = "";
18   if (v11 != '&nbsp;') {
19     if (/^stderr /.test(message)) {
20         if (/^stderr crunchstat: /.test(message)) {
21           type = "crunchstat";
22           message = message.substr(19);
23         } else if (/^stderr srun: /.test(message)) {
24           type = "task-dispatch";
25           message = message.substr(7);
26         } else if (/^stderr slurmd/.test(message)) {
27           type = "task-dispatch";
28           message = message.substr(7);
29         } else {
30           type = "task-output";
31           message = message.substr(7);
32         }
33     } else {
34         type = "task-dispatch";
35     }
36   } else {
37     if (/^status: /.test(message)) {
38         type = "job-status";
39         message = message.substr(8);
40     } else {
41         type = "crunch";
42     }
43   }
44
45     logViewer.add({
46       id: logViewer.items.length,
47       timestamp: ts.toLocaleDateString() + " " + ts.toLocaleTimeString(),
48       taskid: v11,
49       message: message,
50       type: type
51     });
52
53     } else {
54       console.log("Did not parse: " + lines[a]);
55     }
56   }
57   logViewer.update();
58 }
59
60 (function() {
61 var logViewer = new List('log-viewer', {
62   valueNames: [ 'id', 'timestamp', 'taskid', 'message', 'type'],
63   page: 10000,
64 });
65
66 var makeFilter = function() {
67   var pass = [];
68   $(".toggle-filter").each(function(i, e) {
69     if (e.checked) {
70       pass.push(e.id.substr(5));
71     }
72   });
73   return (function(item) {
74     for (a in pass) {
75       if (pass[a] == item.values().type) { return true; }
76     }
77     return false;
78   });
79 }
80
81 <% if @object.log %>
82 <% logcollection = Collection.find @object.log %>
83
84 $.ajax('<%=j url_for logcollection %>/<%=j logcollection.files[0][1] %>').
85   done(function(data, status, jqxhr) {
86     logViewer.filter();
87     addToLogViewer(logViewer, data.split("\n"));
88     logViewer.filter(makeFilter());
89     $("#logloadspinner").detach();
90   });
91 <% else %>
92   <%# Live log loading not implemented yet. %>
93 <% end %>
94
95 $(".toggle-filter").on("change", function() {
96   logViewer.filter(makeFilter());
97 });
98
99 $("#filter-all").on("click", function() {
100   $(".toggle-filter").each(function(i, f) { f.checked = true; });
101   logViewer.filter(makeFilter());
102 });
103
104 $("#filter-none").on("click", function() {
105   $(".toggle-filter").each(function(i, f) { f.checked = false; console.log(f); });
106   logViewer.filter(makeFilter());
107 });
108
109 $("#sort-by-time").on("change", function() {
110   logViewer.sort("id");
111 });
112
113 $("#sort-by-task").on("change", function() {
114   logViewer.sort("taskid");
115 });
116
117 })();
118
119 </script>
120
121 <div id="log-viewer">
122
123     <div class="radio-inline">
124       <label><input id="sort-by-time" type="radio" name="sort-radio" checked> Sort by time</label>
125     </div>
126     <div class="radio-inline">
127       <label><input id="sort-by-task" type="radio" name="sort-radio" > Sort by task</label>
128     </div>
129 <br>
130   <div class="checkbox-inline">
131     <label><input id="show-crunch" type="checkbox" checked="true" class="toggle-filter"> Show crunch output</label>
132   </div>
133   <div class="checkbox-inline">
134     <label><input id="show-job-status" type="checkbox" checked="true" class="toggle-filter"> Show job status</label>
135   </div>
136   <div class="checkbox-inline">
137     <label><input id="show-task-dispatch" type="checkbox" checked="true" class="toggle-filter"> Show task dispatch</label>
138   </div>
139   <div class="checkbox-inline">
140     <label><input id="show-task-output" type="checkbox" checked="true" class="toggle-filter"> Show task output</label>
141   </div>
142   <div class="checkbox-inline">
143     <label><input id="show-crunchstat" type="checkbox" checked="true" class="toggle-filter"> Show compute usage</label>
144   </div>
145
146 <div class="pull-right">
147     <button id="filter-all" class="btn">
148       Select all
149     </button>
150     <button id="filter-none" class="btn">
151       Select none
152     </button>
153 </div>
154
155   <table class="log-viewer-table">
156     <thead>
157       <tr>
158         <th class="id" data-sort="id"></th>
159         <th class="timestamp" data-sort="timestamp">Timestamp</th>
160         <th class="type" data-sort="type">Log type</th>
161         <th class="taskid"  data-sort="taskid">Task</th>
162         <th class="message" data-sort="message">Message</th>
163       </tr>
164     </thead>
165     <tbody class="list">
166       <tr>
167         <td class="id"></td>
168         <td class="timestamp"></td>
169         <td class="type"></td>
170         <td class="taskid"></td>
171         <td class="message"></td>
172       </tr>
173     </tbody>
174   </table>
175
176 </div>
177
178 <% if !@object.log %>
179   This job is still running.  The job log will be available when the job is complete.
180 <% end %>
181
182 <%= image_tag 'ajax-loader.gif', id: "logloadspinner" %>