chiark / gitweb /
journal: add missing browse.html file
[elogind.git] / src / journal / browse.html
1 <!DOCTYPE html>
2 <html>
3 <head>
4         <title>Journal</title>
5         <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
6         <style type="text/css">
7                 div#logs {
8                         font-family: monospace;
9                         font-size: 8pt;
10                         background-color: #ffffff;
11                         padding: 1em;
12                         margin: 2em 0em;
13                         border-radius: 10px 10px 10px 10px;
14                         border: 1px solid threedshadow;
15                         white-space: nowrap;
16                         overflow-x: scroll;
17                 }
18                 body {
19                         background-color: #ededed;
20                         color: #313739;
21                         font: message-box;
22                         margin: 5em;
23                 }
24
25                 .log-error {
26                         color: red;
27                         font-weight: bold;
28                 }
29                 .log-highlight {
30                         font-weight: bold;
31                 }
32         </style>
33 </head>
34
35 <body>
36         <!-- TODO:
37
38                 - seek to back properly
39                 - handle seek before front properly
40                 - show red lines for reboots
41                 - show contents of entries -->
42
43         <h1 id="title"></h1>
44
45         <div id="os"></div>
46         <div id="virtualization"></div>
47         <div id="cutoff"></div>
48         <div id="machine"></div>
49         <div id="usage"></div>
50         <div id="showing"></div>
51
52         <div id="logs"></div>
53
54         <form>
55                 <input id="head" type="button" value="|&lt;" onclick="entriesLoadHead();"/>
56                 <input id="previous" type="button" value="&lt;&lt;" onclick="entriesLoadPrevious();"/>
57                 <input id="next" type="button" value="&gt;&gt;" onclick="entriesLoadNext();"/>
58                 <input id="tail" type="button" value="&gt;|" onclick="entriesLoadTail();"/>
59                 &nbsp;&nbsp;&nbsp;&nbsp;
60                 <input id="more" type="button" value="More" onclick="entriesMore();"/>
61                 <input id="less" type="button" value="Less" onclick="entriesLess();"/>
62         </form>
63
64         <script type="text/javascript">
65                 var first_cursor = null;
66                 var last_cursor = null;
67
68                 function setCookie(name, value, msec) {
69                         var d = new Date();
70                         d.setMilliseconds(d.getMilliseconds() + msec);
71                         var v = escape(value) + "; expires=" + d.toUTCString();
72                         document.cookie = name + "=" + value;
73                 }
74
75                 function getCookie(name) {
76                         var i, l;
77                         l = document.cookie.split(";");
78                         for (i in l) {
79                                 var x, y, j;
80                                 j = l[i].indexOf("=");
81                                 x = l[i].substr(0, j);
82                                 y = l[i].substr(j+1);
83                                 if (x == name)
84                                         return unescape(y);
85                         }
86                         return null;
87                 }
88
89                 function getNEntries() {
90                         var n;
91                         n = getCookie("n_entries");
92                         if (n == null)
93                                 return 50;
94                         return parseInt(n);
95                 }
96
97                 function showNEntries(n) {
98                         var showing = document.getElementById("showing");
99                         showing.innerHTML = "Showing <b>" + n.toString() + "</b> entries.";
100                 }
101
102                 function setNEntries(n) {
103                         if (n < 10)
104                                 n = 10;
105                         else if (n > 1000)
106                                 n = 1000;
107
108                         setCookie("n_entries", n.toString(), 30*24*60*60*1000);
109                         showNEntries(n);
110                 }
111
112                 function machineLoad() {
113                         var request = new XMLHttpRequest();
114                         request.open("GET", "/machine");
115                         request.onreadystatechange = machineOnResult;
116                         request.setRequestHeader("Accept", "application/json");
117                         request.send(null);
118                 }
119
120                 function formatBytes(u) {
121                         if (u >= 1024*1024*1024*1024)
122                                 return (u/1024/1024/1024/1024).toFixed(1) + " TiB";
123                         else if (u >= 1024*1024*1024)
124                                 return (u/1024/1024/1024).toFixed(1) + " GiB";
125                         else if (u >= 1024*1024)
126                                 return (u/1024/1024).toFixed(1) + " MiB";
127                         else if (u >= 1024)
128                                 return (u/1024).toFixed(1) + " KiB";
129                         else
130                                 return u.toString() + " B";
131                 }
132
133                 function machineOnResult(event) {
134                         if ((event.currentTarget.readyState != 4) ||
135                                 (event.currentTarget.status != 200 && event.currentTarget.status != 0))
136                                 return;
137
138                         var d = JSON.parse(event.currentTarget.responseText);
139
140                         var title = document.getElementById("title");
141                         title.innerHTML = 'Journal of ' + d.hostname;
142                         document.title = 'Journal of ' + d.hostname;
143
144                         var machine = document.getElementById("machine");
145                         machine.innerHTML = 'Machine ID is <b>' + d.machine_id + '</b>, current boot ID is <b>' + d.boot_id + '</b>.';
146
147                         var cutoff = document.getElementById("cutoff");
148                         var from = new Date(parseInt(d.cutoff_from_realtime) / 1000);
149                         var to = new Date(parseInt(d.cutoff_to_realtime) / 1000);
150                         cutoff.innerHTML = 'Journal begins at <b>' + from.toLocaleString() + '</b> and ends at <b>' + to.toLocaleString() + '</b>.';
151
152                         var usage = document.getElementById("usage");
153                         usage.innerHTML = 'Disk usage is <b>' + formatBytes(parseInt(d.usage)) + '</b>.';
154
155                         var os = document.getElementById("os");
156                         os.innerHTML = 'Operating system is <b>' + d.os_pretty_name + '</b>.';
157
158                         var virtualization = document.getElementById("virtualization");
159                         virtualization.innerHTML = d.virtualization == "bare" ? "Running on <b>bare metal</b>." : "Running on virtualization <b>" + d.virtualization + "</b>.";
160                 }
161
162                 function entriesLoad(range) {
163                         var request = new XMLHttpRequest();
164                         request.open("GET", "/entries");
165                         request.onreadystatechange = entriesOnResult;
166                         request.setRequestHeader("Accept", "application/json");
167                         request.setRequestHeader("Range", "entries=" + range + ":" + getNEntries().toString());
168                         request.send(null);
169                 }
170
171                 function entriesLoadNext() {
172                         if (last_cursor == null)
173                                 entriesLoad("");
174                         else
175                                 entriesLoad(last_cursor + ":1");
176                 }
177
178                 function entriesLoadPrevious() {
179                         if (first_cursor == null)
180                                 entriesLoad("");
181                         else
182                                 entriesLoad(first_cursor + ":-" + getNEntries().toString());
183                 }
184
185                 function entriesLoadHead() {
186                         entriesLoad("");
187                 }
188
189                 function entriesLoadTail() {
190                         entriesLoad(":-" + getNEntries().toString());
191                 }
192
193                 function entriesOnResult(event) {
194
195                         if ((event.currentTarget.readyState != 4) ||
196                                 (event.currentTarget.status != 200 && event.currentTarget.status != 0))
197                                 return;
198
199                         var logs = document.getElementById("logs");
200                         logs.innerHTML = "";
201
202                         var lc = null;
203                         var fc = null;
204
205                         var i;
206                         var l = event.currentTarget.responseText.split('\n');
207
208                         if (l.length <= 1) {
209                                 logs.innerHTML = "<i>No further entries...</i>";
210                                 return;
211                         }
212
213                         for (i in l) {
214
215                                 if (l[i] == '')
216                                         continue;
217
218                                 var d = JSON.parse(l[i]);
219                                 if (d.MESSAGE == undefined || d.__CURSOR == undefined)
220                                         continue;
221
222                                 if (fc == null)
223                                         fc = d.__CURSOR;
224                                 lc = d.__CURSOR;
225
226                                 var priority;
227                                 if (d.PRIORITY != undefined)
228                                         priority = parseInt(d.PRIORITY);
229                                 else
230                                         priority = 6;
231
232                                 if (priority <= 3)
233                                         clazz = "log-error";
234                                 else if (priority <= 5)
235                                         clazz = "log-highlight";
236                                 else
237                                         clazz = "log-normal";
238
239                                 var line = '<div class="' + clazz + '">';
240
241                                 if (d.SYSLOG_IDENTIFIER != undefined)
242                                         line += d.SYSLOG_IDENTIFIER;
243                                 else if (d._COMM != undefined)
244                                         line += d._COMM;
245
246                                 if (d._PID != undefined)
247                                         line += "[" + d._PID + "]";
248                                 else if (d.SYSLOG_PID != undefined)
249                                         line += "[" + d.SYSLOG_PID + "]";
250
251                                 if (d.MESSAGE == null)
252                                         line += ": [blob data]</div>";
253                                 else if (d.MESSAGE instanceof Array)
254                                         line += ": [" + formatBytes(d.MESSAGE.length) + " blob data]</div>";
255                                 else
256                                         line += ": " + d.MESSAGE + "</div>";
257
258                                 logs.innerHTML += line;
259                         }
260
261                         if (fc != null)
262                                 first_cursor = fc;
263                         if (lc != null)
264                                 last_cursor = lc;
265                 }
266
267                 function entriesMore() {
268                         setNEntries(getNEntries() + 10);
269                         entriesLoad("");
270                 }
271
272                 function entriesLess() {
273                         setNEntries(getNEntries() - 10);
274                         entriesLoad("");
275                 }
276
277                 machineLoad();
278                 entriesLoad("");
279                 showNEntries(getNEntries());
280         </script>
281 </body>
282 </html>