]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/journal/browse.html
journal: add missing browse.html file
[thirdparty/systemd.git] / src / journal / browse.html
CommitLineData
bf5542f8
LP
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>