FOSSology  3.2.0rc1
Open Source License Compliance by Open Source Software
admin-dashboard-general.php
1 <?php
2 /***********************************************************
3  Copyright (C) 2008-2013 Hewlett-Packard Development Company, L.P.
4  Copyright (C) 2015-2018 Siemens AG
5  Copyright (C) 2019 Orange
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License
9  version 2 as published by the Free Software Foundation.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License along
17  with this program; if not, write to the Free Software Foundation, Inc.,
18  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  ***********************************************************/
20 
21 define("TITLE_DASHBOARD_GENERAL", _("Overview Dashboard"));
22 
24 
25 class dashboard extends FO_Plugin
26 {
27  protected $pgVersion;
28 
30  private $dbManager;
31 
32  function __construct()
33  {
34  $this->Name = "dashboard";
35  $this->Title = TITLE_DASHBOARD_GENERAL;
36  $this->MenuList = "Admin::Dashboards::Overview";
37  $this->DBaccess = PLUGIN_DB_ADMIN;
38  parent::__construct();
39  $this->dbManager = $GLOBALS['container']->get('db.manager');
40  }
41 
46  function DatabaseContentsRow($TableName, $TableLabel)
47  {
48  $row = $this->dbManager->getSingleRow(
49  "select sum(reltuples) as val from pg_class where relname like $1 and reltype !=0",
50  array($TableName),
51  __METHOD__);
52  $item_count = $row['val'];
53 
54  $V = "<tr><td>$TableLabel</td>";
55  $V .= "<td align='right'>" . number_format($item_count,0,"",",") . "</td>";
56 
57  $LastVacTime = $this->GetLastVacTime($TableName);
58  if (empty($LastVacTime)) {
59  $mystyle = "style=background-color:red";
60  } else {
61  $mystyle = "";
62  }
63  $V .= "<td $mystyle>" . substr($LastVacTime, 0, 16) . "</td>";
64 
65  $LastAnalyzeTime = $this->GetLastAnalyzeTime($TableName);
66  if (empty($LastAnalyzeTime)) {
67  $mystyle = "style=background-color:red";
68  } else {
69  $mystyle = "";
70  }
71  $V .= "<td $mystyle>" . substr($LastAnalyzeTime, 0, 16) . "</td>";
72 
73  $V .= "</tr>\n";
74  return $V;
75  }
76 
81  function DatabaseContents()
82  {
83  $V = "<table border=1>\n";
84 
85  $head1 = _("Metric");
86  $head2 = _("Total");
87  $head3 = _("Last<br>Vacuum");
88  $head4 = _("Last<br>Analyze");
89  $V .= "<tr><th>$head1</th><th>$head2</th><th>$head3</th><th>$head4</th></tr>\n";
90 
91  /**** Users ****/
92  $V .= $this->DatabaseContentsRow("users", _("Users"));
93 
94  /**** Uploads ****/
95  $V .= $this->DatabaseContentsRow("upload", _("Uploads"));
96 
97  /**** Unique pfiles ****/
98  $V .= $this->DatabaseContentsRow("pfile", _("Unique files referenced in repository"));
99 
100  /**** uploadtree recs ****/
101  $V .= $this->DatabaseContentsRow("uploadtree_%", _("Individual Files"));
102 
103  /**** License recs ****/
104  $V .= $this->DatabaseContentsRow("license_file", _("Discovered Licenses"));
105 
106  /**** Copyright recs ****/
107  $V .= $this->DatabaseContentsRow("copyright", _("Copyrights/URLs/Emails"));
108 
109  $V .= "</table>\n";
110 
111  return $V;
112  }
113 
114  function GetLastAnalyzeTimeOrVacTime($queryPart,$TableName)
115  {
116  $sql = "select greatest($queryPart) as lasttime from pg_stat_all_tables where schemaname = 'public' and relname like $1";
117  $row = $this->dbManager->getSingleRow($sql, array($TableName), __METHOD__);
118 
119  return $row["lasttime"];
120  }
121 
122  function GetLastVacTime($TableName)
123  {
124  return $this->GetLastAnalyzeTimeOrVacTime("last_vacuum, last_autovacuum",$TableName);
125  }
126 
127  function GetPHPInfoTable()
128  {
129  $PHP_VERSION = phpversion();
130  $loadedModules = get_loaded_extensions();
131 
132  $table = "
133 <table class='infoTable' border=1>
134  <tr>
135  <th>
136  Info
137  </th>
138  <th>
139  Value
140  </th>
141  </tr>
142  <tbody>
143  <tr>
144  <td>
145  PHP Version
146  </td>
147  <td>
148  $PHP_VERSION
149  </td>
150  </tr>
151  <tr>
152  <td>
153  Loaded Extensions
154  </td>
155  <td><div class='infoTable'>";
156  foreach ($loadedModules as $currentExtensionName) {
157  $currentVersion = phpversion($currentExtensionName);
158  $table .= $currentExtensionName . ": " . $currentVersion . "<br />";
159  }
160 
161  $table .="</div></td>
162  </tr>
163  </tbody>
164 </table>
165 
166  ";
167  return $table;
168  }
169 
170  function GetLastAnalyzeTime($TableName)
171  {
172  return $this->GetLastAnalyzeTimeOrVacTime("last_analyze, last_autoanalyze",
173  $TableName);
174  }
175 
176 
181  function DatabaseMetrics()
182  {
183 
184  $V = "<table border=1>\n";
185  $text = _("Metric");
186  $text1 = _("Total");
187  $V .= "<tr><th>$text</th><th>$text1</th></tr>\n";
188 
189  /* Database size */
190  $sql = "SELECT pg_database_size('fossology') as val;";
191  $row = $this->dbManager->getSingleRow($sql, array(), __METHOD__."get_Size");
192  $Size = HumanSize($row['val']);
193  $text = _("FOSSology database size");
194  $V .= "<tr><td>$text</td>";
195  $V .= "<td align='right'> $Size </td></tr>\n";
196 
197  /**** Version ****/
198  $text = _("Postgresql version");
199  $V .= "<tr><td>$text</td>";
200  $V .= "<td align='right'> {$this->pgVersion['server']} </td></tr>\n";
201 
202  /**** Query stats ****/
203  // count current queries
204  $sql = "SELECT count(*) AS val FROM pg_stat_activity";
205  $row = $this->dbManager->getSingleRow($sql, array(), __METHOD__."get_connection_count");
206  $connection_count = $row['val'];
207 
208  /**** Active connection count ****/
209  $text = _("Active database connections");
210  $V .= "<tr><td>$text</td>";
211  $V .= "<td align='right'>" . number_format($connection_count,0,"",",") . "</td></tr>\n";
212 
213  $V .= "</table>\n";
214 
215  return $V;
216  }
217 
218 
223  function DatabaseQueries()
224  {
225  $V = "<table border=1 id='databaseTable'>\n";
226  $head1 = _("PID");
227  $head2 = _("Query");
228  $head3 = _("Started");
229  $head4 = _("Elapsed");
230  $V .= "<tr><th>$head1</th><th>$head2</th><th>$head3</th><th>$head4</th></tr>\n";
231  $getCurrentVersion = explode(" ", $this->pgVersion['server']);
232  $currentVersion = str_replace(".", "", $getCurrentVersion[0]);
233  unset($getCurrentVersion);
234  $oldVersion = str_replace(".", "", "9.2");
235  $current_query = ($currentVersion >= $oldVersion) ? "state" : "current_query";
236  $procpid = ($currentVersion >= $oldVersion) ? "pid" : "procpid";
237  $sql = "SELECT $procpid processid, $current_query, query_start, now()-query_start AS elapsed FROM pg_stat_activity WHERE $current_query != '<IDLE>' AND datname = 'fossology' ORDER BY $procpid";
238 
239  $statementName = __METHOD__."queryFor_".$current_query."_orderBy_".$procpid;
240  $this->dbManager->prepare($statementName,$sql);
241  $result = $this->dbManager->execute($statementName, array());
242 
243  if (pg_num_rows($result) > 1) {
244  while ($row = pg_fetch_assoc($result)) {
245  if ($row[$current_query] == $sql) {
246  continue; // Don't display this query
247  }
248  $V .= "<tr>";
249  $V .= "<td class='dashboard'>$row[processid]</td>";
250  $V .= "<td class='dashboard'>" . htmlspecialchars($row[$current_query]) .
251  "</td>";
252  $StartTime = Convert2BrowserTime(substr($row['query_start'], 0, 19));
253  $V .= "<td class='dashboard'>$StartTime</td>";
254  $V .= "<td class='dashboard'>$row[elapsed]</td>";
255  $V .= "</tr>\n";
256  }
257  } else {
258  $V .= "<tr><td class='dashboard' colspan=4>There are no active FOSSology queries</td></tr>";
259  }
260 
261  pg_free_result($result);
262  $V .= "</table>\n";
263 
264  return $V;
265  }
266 
267 
271  function DiskFree()
272  {
273  global $SYSCONFDIR;
274  global $SysConf;
275 
276  $Cmd = "df -hP";
277  $Buf = $this->DoCmd($Cmd);
278 
279  /* Separate lines */
280  $Lines = explode("\n",$Buf);
281 
282  /* Display results */
283  $V = "";
284  $V .= "<table border=1>\n";
285  $head0 = _("Filesystem");
286  $head1 = _("Capacity");
287  $head2 = _("Used");
288  $head3 = _("Available");
289  $head4 = _("Percent Full");
290  $head5 = _("Mount Point");
291  $V .= "<tr><th>$head0</th><th>$head1</th><th>$head2</th><th>$head3</th><th>$head4</th><th>$head5</th></tr>\n";
292  $headerline = true;
293  foreach ($Lines as $L) {
294  // Skip top header line
295  if ($headerline) {
296  $headerline = false;
297  continue;
298  }
299 
300  if (empty($L)) {
301  continue;
302  }
303  $L = trim($L);
304  $L = preg_replace("/[[:space:]][[:space:]]*/", " ", $L);
305  $List = explode(" ", $L);
306 
307  // Skip some filesystems we are not interested in
308  if ($List[0] == 'tmpfs') {
309  continue;
310  }
311  if ($List[0] == 'udev') {
312  continue;
313  }
314  if ($List[0] == 'none') {
315  continue;
316  }
317  if ($List[5] == '/boot') {
318  continue;
319  }
320 
321  $V .= "<tr><td>" . htmlentities($List[0]) . "</td>";
322  $V .= "<td align='right' style='border-right:none'>$List[1]</td>";
323  $V .= "<td align='right' style='border-right:none'>$List[2]</td>";
324  $V .= "<td align='right' style='border-right:none'>$List[3]</td>";
325 
326  // Warn if running out of disk space
327  $PctFull = (int) $List[4];
328  $WarnAtPct = 90; // warn the user if they exceed this % full
329  if ($PctFull > $WarnAtPct) {
330  $mystyle = "style=border-right:none;background-color:red";
331  } else {
332  $mystyle = "style='border-right:none'";
333  }
334  $V .= "<td align='right' $mystyle>$List[4]</td>";
335 
336  $V .= "<td align='left'>" . htmlentities($List[5]) . "</td></tr>\n";
337  }
338  $V .= "</table>\n";
339 
340  /*** Print out important file paths so users can interpret the above "df" ***/
341  $V .= _("Note:") . "<br>";
342  $Indent = "&nbsp;&nbsp;";
343 
344  // File path to the database
345  $V .= $Indent . _("Database"). ": " . "&nbsp;";
346  // Get the database data_directory. If we were the superuser we could
347  // just query the database with "show data_directory", but we are not.
348  // So try to get it from a ps and parse the -D argument
349  $Cmd = "ps -eo cmd | grep postgres | grep -- -D";
350  $Buf = $this->DoCmd($Cmd);
351  // Find the -D
352  $DargToEndOfStr = trim(substr($Buf, strpos($Buf, "-D") + 2 ));
353  $DargArray = explode(' ', $DargToEndOfStr);
354  $V .= $DargArray[0] . "<br>";
355 
356  // Repository path
357  $V .= $Indent . _("Repository") . ": " . $SysConf['FOSSOLOGY']['path'] . "<br>";
358 
359  // FOSSology config location
360  $V .= $Indent . _("FOSSology config") . ": " . $SYSCONFDIR . "<br>";
361 
362  return($V);
363  }
364 
365  public function Output()
366  {
367  global $PG_CONN;
368  $this->pgVersion = pg_version($PG_CONN);
369 
370  $V="";
371  $V .= "<table style='width: 100%;' border=0>\n";
372  $V .= "<tr>";
373  $V .= "<td valign='top'>\n";
374  $text = _("Database Contents");
375  $V .= "<h2>$text</h2>\n";
376  $V .= $this->DatabaseContents();
377  $V .= "</td>";
378 
379  $V .= "<td class='dashboard'>\n";
380  $text = _("Database Metrics");
381  $V .= "<h2>$text</h2>\n";
382  $V .= $this->DatabaseMetrics();
383  $V .= "</td>";
384  $V .= "</tr>";
385 
386  $V .= "<tr>";
387  $V .= "<td class='dashboard'>";
388  $text = _("Active FOSSology queries");
389  $V .= "<h2>$text</h2>\n";
390  $V .= $this->DatabaseQueries();
391  $V .= "</td>";
392 
393  $V .= "<td class='dashboard'>";
394  $text = _("PHP Info");
395  $V .= "<h2>$text</h2>\n";
396  $V .= $this->GetPHPInfoTable();
397  $V .= "</td>";
398  $V .= "</tr>";
399 
400  $V .= "<tr>";
401  $V .= "<td class='dashboard'>";
402  $text = _("Disk Space");
403  $V .= "<h2>$text</h2>\n";
404  $V .= $this->DiskFree();
405  $V .= "</td>";
406  $V .= "</tr>";
407 
408  $V .= "</table>\n";
409  $V .= "<br><br>";
410  return $V;
411  }
412 
418  protected function DoCmd($cmd)
419  {
420  $fin = popen($cmd, "r");
421  $buffer = "";
422  while (! feof($fin)) {
423  $buffer .= fread($fin, 8192);
424  }
425  pclose($fin);
426  return $buffer;
427  }
428 }
429 
430 $NewPlugin = new dashboard;
431 $NewPlugin->Initialize();
DatabaseContentsRow($TableName, $TableLabel)
Return each html row for DatabaseContents()
#define PLUGIN_DB_ADMIN
Plugin requires admin level permission on DB.
Definition: libfossology.h:51
Convert2BrowserTime($server_time)
Convert the server time to browser time.
Definition: common-ui.php:298
DoCmd($cmd)
execute a shell command
DatabaseContents()
Database Contents metrics.
DatabaseMetrics()
Database metrics.
fo_dbManager * dbManager
fo_dbManager object
Definition: process.c:28
This is the Plugin class. All plugins should:
Definition: FO_Plugin.php:67
DatabaseQueries()
Database queries.
DiskFree()
Determine amount of free disk space.
foreach($Options as $Option=> $OptVal) if(0==$reference_flag &&0==$nomos_flag) $PG_CONN
HumanSize($bytes)
Translate a byte number to a proper type, xxx bytes to xxx B/KB/MB/GB/TB/PB.
Definition: common-ui.php:109
char * trim(char *ptext)
Trimming whitespace.
Definition: fossconfig.c:695