5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
6 <style type="text/css">
8 font-family: monospace;
10 background-color: #ffffff;
13 border-radius: 10px 10px 10px 10px;
14 border: 1px solid threedshadow;
19 background-color: #ededed;
38 - seek to back properly
39 - handle seek before front properly
40 - show red lines for reboots
41 - show contents of entries -->
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>
55 <input id="head" type="button" value="|<" onclick="entriesLoadHead();"/>
56 <input id="previous" type="button" value="<<" onclick="entriesLoadPrevious();"/>
57 <input id="next" type="button" value=">>" onclick="entriesLoadNext();"/>
58 <input id="tail" type="button" value=">|" onclick="entriesLoadTail();"/>
59
60 <input id="more" type="button" value="More" onclick="entriesMore();"/>
61 <input id="less" type="button" value="Less" onclick="entriesLess();"/>
64 <script type="text/javascript">
65 var first_cursor = null;
66 var last_cursor = null;
68 function setCookie(name, value, msec) {
70 d.setMilliseconds(d.getMilliseconds() + msec);
71 var v = escape(value) + "; expires=" + d.toUTCString();
72 document.cookie = name + "=" + value;
75 function getCookie(name) {
77 l = document.cookie.split(";");
80 j = l[i].indexOf("=");
81 x = l[i].substr(0, j);
89 function getNEntries() {
91 n = getCookie("n_entries");
97 function showNEntries(n) {
98 var showing = document.getElementById("showing");
99 showing.innerHTML = "Showing <b>" + n.toString() + "</b> entries.";
102 function setNEntries(n) {
108 setCookie("n_entries", n.toString(), 30*24*60*60*1000);
112 function machineLoad() {
113 var request = new XMLHttpRequest();
114 request.open("GET", "/machine");
115 request.onreadystatechange = machineOnResult;
116 request.setRequestHeader("Accept", "application/json");
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";
128 return (u/1024).toFixed(1) + " KiB";
130 return u.toString() + " B";
133 function machineOnResult(event) {
134 if ((event.currentTarget.readyState != 4) ||
135 (event.currentTarget.status != 200 && event.currentTarget.status != 0))
138 var d = JSON.parse(event.currentTarget.responseText);
140 var title = document.getElementById("title");
141 title.innerHTML = 'Journal of ' + d.hostname;
142 document.title = 'Journal of ' + d.hostname;
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>.';
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>.';
152 var usage = document.getElementById("usage");
153 usage.innerHTML = 'Disk usage is <b>' + formatBytes(parseInt(d.usage)) + '</b>.';
155 var os = document.getElementById("os");
156 os.innerHTML = 'Operating system is <b>' + d.os_pretty_name + '</b>.';
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>.";
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());
171 function entriesLoadNext() {
172 if (last_cursor == null)
175 entriesLoad(last_cursor + ":1");
178 function entriesLoadPrevious() {
179 if (first_cursor == null)
182 entriesLoad(first_cursor + ":-" + getNEntries().toString());
185 function entriesLoadHead() {
189 function entriesLoadTail() {
190 entriesLoad(":-" + getNEntries().toString());
193 function entriesOnResult(event) {
195 if ((event.currentTarget.readyState != 4) ||
196 (event.currentTarget.status != 200 && event.currentTarget.status != 0))
199 var logs = document.getElementById("logs");
206 var l = event.currentTarget.responseText.split('\n');
209 logs.innerHTML = "<i>No further entries...</i>";
218 var d = JSON.parse(l[i]);
219 if (d.MESSAGE == undefined || d.__CURSOR == undefined)
227 if (d.PRIORITY != undefined)
228 priority = parseInt(d.PRIORITY);
234 else if (priority <= 5)
235 clazz = "log-highlight";
237 clazz = "log-normal";
239 var line = '<div class="' + clazz + '">';
241 if (d.SYSLOG_IDENTIFIER != undefined)
242 line += d.SYSLOG_IDENTIFIER;
243 else if (d._COMM != undefined)
246 if (d._PID != undefined)
247 line += "[" + d._PID + "]";
248 else if (d.SYSLOG_PID != undefined)
249 line += "[" + d.SYSLOG_PID + "]";
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>";
256 line += ": " + d.MESSAGE + "</div>";
258 logs.innerHTML += line;
267 function entriesMore() {
268 setNEntries(getNEntries() + 10);
272 function entriesLess() {
273 setNEntries(getNEntries() - 10);
279 showNEntries(getNEntries());