- use AJAX to avoid loading DEBUG messages (breaks firefox by multi-MB log files)
[oweals/gnunet.git] / contrib / log.php
1 <?php
2
3 $path='log';
4 $lines = array();
5 $ajax = FALSE;
6
7 function render_row ($d, $component, $pid, $level, $msg, $c)
8 {
9   global $ajax;
10   if (!$ajax && $level == "DEBUG")
11     return;
12   $date = $d ? $d->format('Y-m-d'). '<br />' . $d->format('H:i:s') : "";
13   echo "<tr class=\"$level\" id=\"$c\">";
14   echo "<td class=\"date\"><small>$date</small></td>";
15   echo '<td class="usec">';
16   echo $d ? $d->format('u') : "";
17   echo '</td>';
18   echo "<td class=\"comp\">$component</td><td class=\"level\">$level</td><td>$msg&nbsp;</td>";
19   if ($level != "DEBUG")
20   {
21     echo '<td><button class="btn btn-xs btn-default btn-showup"><span class="glyphicon glyphicon-chevron-up"></span></button>';
22     echo '<button class="btn btn-xs btn-default btn-showdown"><span class="glyphicon glyphicon-chevron-down"></span></button></td></tr>';
23   }
24   else
25     echo '<td></td></tr>';
26 }
27
28 function render_rows ()
29 {
30   global $lines;
31   foreach ($lines as $line) {
32     render_row ($line[0], $line[1], $line[2], $line[3], $line[4], $line[5]);
33   }
34 }
35
36 function process ($line, $c)
37 {
38   global $lines;
39   $a = explode (' ', $line);
40   if (count($a) < 6)
41     return;
42   $date = DateTime::createFromFormat ("M d H:i:s-u", implode (' ', array_slice ($a, 0, 3)));
43   $component = $a[3];
44   $level = $a[4];
45   $msg = implode (' ', array_slice ($a, 5));
46   
47   $lines[] = array ($date, $component, 0, $level, $msg, $c);
48 }
49
50 if (array_key_exists ('a', $_GET)) {
51   $start = (int)$_GET['a'];
52   $ajax= TRUE;
53 }
54 else
55 {
56   $start = null;
57 }
58 if (array_key_exists ('z', $_GET)) {
59   $stop = (int)$_GET['z'];
60   $ajax= TRUE;
61 }
62 else
63 {
64   $stop = null;
65 }
66 $t0 = microtime(true);
67 $handle = @fopen($path, 'r');
68 if ($handle) {
69     $c = 0;
70     while (($line = fgets($handle)) !== false) {
71         if ((!$start || $c >= $start) && (!$stop || $c <= $stop)) {
72           process ($line, $c);
73         }
74         $c++;
75     }
76 } else {
77    echo "<div class=\"alert alert-danger\">Error opening file $path.</div>";
78 }
79
80 $t1 = microtime(true);
81 if ($start !== null || $stop !== null) {
82   render_rows();
83   die();
84 }
85 // echo $t1-$t0;
86
87 ?>
88 <!DOCTYPE html>
89 <html lang="en">
90 <head>
91   <meta charset="utf-8">
92   <meta http-equiv="X-UA-Compatible" content="IE=edge">
93   <meta name="viewport" content="width=device-width, initial-scale=1">
94   
95   <title>GNUnet log view</title>
96
97   <!-- Latest compiled and minified Bootstrap CSS -->
98   <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.0/css/bootstrap.min.css">
99   <!-- Optional theme -->
100   <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.0/css/bootstrap-theme.min.css">
101
102   <style>
103     body {
104       font-family: arial,sans-serif;
105       color:#444;
106     }
107     table {
108       font-size:12px;
109       border-collapse:collapse;
110     }
111     .alert {
112       display: none;
113       position: fixed;
114       width: 75%;
115       left: 50%;
116       margin: 0 0 0 -37.5%;
117     }
118     .level {
119       display: none;
120     }
121     .DEBUG {
122       background-color:#CCC;
123     }
124     .WARNING {
125       background-color:#EB9316;
126     }
127     .ERROR {
128       background-color:#D2322D;
129     }
130
131   </style>
132 </head>
133
134
135 <body>
136 <div class="btn-toolbar" role="toolbar">
137   <div class="btn-group">
138     <button class="btn btn-danger btn-showerror"><span class="glyphicon glyphicon-fire"></span> Error</button>
139     <button class="btn btn-warning btn-showwarn"><span class="glyphicon glyphicon-exclamation-sign"></span> Warning</button>
140     <button class="btn btn-info btn-showinfo"><span class="glyphicon glyphicon glyphicon-info-sign"></span> Info</button>
141     <button class="btn btn-default btn-showdebug"><span class="glyphicon glyphicon glyphicon-wrench"></span> Debug</button>
142 </div>
143 </div>
144 <div id="msg" class="alert alert-success"></div>
145 <table class="table">
146   <thead>
147   <tr>
148     <th>Date Time</th>
149     <th>uSec</th>
150     <th>Comp</th>
151     <th class="level">Level</th>
152     <th>Message</th>
153     <th></th>
154   </tr>
155   </thead>
156   <tbody>
157 <?php render_rows(); ?>
158   </tbody>
159 </table>
160   <!-- jQuery -->
161   <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
162   <!-- Latest compiled and minified Bootstrap JavaScript -->
163   <script src="//netdna.bootstrapcdn.com/bootstrap/3.1.0/js/bootstrap.min.js"></script>
164
165   <script>
166
167     var types = ["ERROR", "WARNING", "INFO", "DEBUG"];
168     var msg_timeout;
169
170     function msg (content)
171     {
172       $("#msg").html(content);
173       $("#msg").stop(true);
174       $("#msg").fadeTo(100, 1).fadeTo(3000, 0.90).fadeOut(1000);
175     }
176
177     function showlevel (level)
178     {
179       $("tr").hide();
180       for (var index = 0; index < types.length; ++index) {
181         $("."+types[index]).show();
182         if (types[index] == level)
183           return;
184       }
185     }
186
187     function show (btn, up)
188     {
189       var tr = $(btn).parents("tr");
190       var level = tr.attr("class");
191       var pos = parseInt(tr.attr("id"));
192       var first = pos + 1;
193       var last = pos - 1;
194       if (up) {
195         if (parseInt(tr.prev().attr("id")) == last) {
196           msg ("Already loaded");
197           return;
198         }
199         first = parseInt(tr.prevAll("."+level).first().attr("id")) + 1;
200         first = isNaN(first) ? 0 : first;
201       } else {
202         if (parseInt(tr.next().attr("id")) == first) {
203           msg ("Already loaded");
204           return;
205         }
206         last = parseInt(tr.nextAll("."+level).first().attr("id")) - 1;
207       }
208       if (first > last)
209         return;
210       $.ajax({
211         url: document.location,
212         data: { a: first, z: last }
213       }).done(function ( resp ) {
214         var loc = $("#"+(first-1));
215         if (loc.length > 0)
216           loc.after(resp);
217         else {
218           $("#"+(last+1)).before(resp);
219         }
220         msg("Done loading " + (last-first+1) + " lines.");
221       });
222       //tr.nextUntil("."+tr.attr("class")).show();
223       
224     }
225
226     function hide (btn)
227     {
228       var tr = $(btn).parents("tr");
229       tr.nextUntil("."+tr.attr("class")).hide();
230     }
231
232     $(function() {
233       $(".btn-showup").on ("click", function(){ show(this, true) });
234       $(".btn-showdown").on ("click", function(){ show(this, false) });
235       $(".btn-showerror").on ("click", function(){ showlevel("ERROR") });
236       $(".btn-showwarn").on ("click", function(){ showlevel("WARNING") });
237       $(".btn-showinfo").on ("click", function(){ showlevel("INFO") });
238       $(".btn-showdebug").on ("click", function(){ showlevel("DEBUG") });
239     });
240   </script>
241 </body>
242 </html>