source: genapp/languages/html5/sys/sys_jobmonitor.php @ 490

Last change on this file since 490 was 490, checked in by ehb, 7 years ago
File size: 16.8 KB
Line 
1#!/usr/local/bin/php
2<?php
3
4$_REQUEST = json_decode( $argv[ 1 ], true );
5
6
7$results = [];
8
9if ( !sizeof( $_REQUEST ) ) {
10    $results[ 'error' ] = "PHP code received no \$_REQUEST?";
11    echo (json_encode($results));
12    exit();
13}
14
15if ( !isset( $_REQUEST[ '_uuid' ] ) ) {
16    $results[ "error" ] = "No _uuid specified in the request";
17    echo (json_encode($results));
18    exit();
19}
20
21if ( !isset( $_REQUEST[ '_logon' ] ) ) {
22    $results[ "error" ] = "No _logon specified in the request";
23    echo (json_encode($results));
24    exit();
25}
26
27if ( !isset( $_REQUEST[ 'interval' ] ) ) {
28    $results[ "error" ] = "Insufficient request data";
29    echo (json_encode($results));
30    exit();
31}
32
33$appconfig = json_decode( file_get_contents( "__appconfig__" ) );
34
35if ( !isset( $appconfig->messaging->zmqhostip ) ||
36     !isset( $appconfig->messaging->zmqport )   || 
37     !isset( $appconfig->admin ) ) {
38    $results[ "error" ] = "appconfig.json missing zmq or admin info";
39    echo (json_encode($results));
40    exit();
41}   
42
43if ( !in_array( $_REQUEST[ '_logon' ], $appconfig->admin ) ) {
44    $results[ "error" ] = "not an administrator";
45    echo (json_encode($results));
46    exit();
47}   
48
49date_default_timezone_set("UTC");
50
51$context = new ZMQContext();
52$zmq_socket = $context->getSocket(ZMQ::SOCKET_PUSH, '__application__ udp pusher');
53$zmq_socket->connect("tcp://" . $appconfig->messaging->zmqhostip . ":" . $appconfig->messaging->zmqport );
54
55function db_connect( $error_json_exit = false ) {
56   global $use_db;
57   global $db_errors;
58
59   if ( !isset( $use_db ) ) {
60      try {
61         $use_db = new MongoClient();
62      } catch ( Exception $e ) {
63         $db_errors = "Could not connect to the db " . $e->getMessage();
64         if ( $error_json_exit )
65         {
66            $results = array( "error" => $db_errors );
67            $results[ '_status' ] = 'complete';
68            echo (json_encode($results));
69            exit();
70         }
71         return false;
72      }
73   }
74
75   return true;
76}
77
78function ProcStats( $sys ) {
79    global $appconfig;
80
81    $result = array();
82
83    $cmd = $appconfig->resources->{ $sys };
84    $ucmd = "head -1 /proc/stat; cat /proc/meminfo; echo cut_here; cat /proc/net/dev";
85
86    if ( strlen( $cmd ) ) {
87        $cmd .= " \"$ucmd\"";
88    } else {
89        $cmd = $ucmd;
90    }
91    exec( $cmd, $res );
92
93    $a = explode( ' ', array_shift( $res ) );
94    array_shift( $a );
95    while( !$a[ 0 ] ) {
96        array_shift( $a );
97    }
98    $result[ "cpu" ] = $a;
99
100    $res2 = [];
101    $restmp = [];
102    foreach ( $res as $v ) {
103        if ( $v == "cut_here" ) {
104            $res2[] = $restmp;
105            $restmp = [];
106        } else {
107            $restmp[] = $v;
108        }
109    }
110    if ( count( $restmp ) ) {
111        $res2[] = $restmp;
112    }
113
114    // compute mem info
115    $tmpmem = array();
116    $meminterest = preg_grep( "/^(Mem|Swap)(Free|Total):/", $res2[0] );
117    foreach ( $meminterest as $v ) {
118        preg_match( "/^(\S+):\s+(\d+)\s+/", $v, $matches );
119        if ( count( $matches ) == 3 ) {
120            $tmpmem[ $matches[ 1 ] ] = $matches[ 2 ];
121        }
122    }
123
124    // compute useful bits
125    $result[ "mem" ] = array();
126    $result[ "mem" ][ "memused" ] =
127        (
128          isset( $tmpmem[ "MemTotal" ] ) &&
129          isset( $tmpmem[ "MemFree" ] ) &&
130          $tmpmem[ "MemTotal" ] > 0
131        )
132        ?
133        round( 100.0 * ( $tmpmem[ "MemTotal" ] - $tmpmem[ "MemFree" ] ) / $tmpmem[ "MemTotal" ], 1 )
134        :
135        100.0
136        ;
137         
138    $result[ "mem" ][ "swapused" ] =
139        (
140          isset( $tmpmem[ "SwapTotal" ] ) &&
141          isset( $tmpmem[ "SwapFree" ] ) &&
142          $tmpmem[ "SwapTotal" ] > 0
143        )
144        ?
145        round( 100.0 * ( $tmpmem[ "SwapTotal" ] - $tmpmem[ "SwapFree" ] ) / $tmpmem[ "SwapTotal" ], 1 )
146        :
147        0.0
148        ;
149       
150    // network
151
152    $net = array_slice( $res2[ 1 ], 2 );   
153
154    $result[ "net" ] = array();
155
156    foreach ( $net as $v ) {
157        $thisnet = preg_split( "/\s+/", $v );
158        $if = rtrim( $thisnet[ 1 ], ":" );
159        // for sep tx,rx $result[ "net" ][ $if ] = array( $thisnet[ 2 ], $thisnet[ 10 ] );
160        $totuse = $thisnet[ 2 ] + $thisnet[ 10 ];
161        // skip lo for now
162        if ( $totuse > 0 && $if != "lo" ) {
163            $result[ "net" ][ $if ] = $totuse;
164        }
165    }       
166
167    return $result;
168}
169
170function UpdateStats( $sys, $init = false ) {
171    global $load;
172    $load[ $sys ][ "prev" ] = $load[ $sys ][ "this" ];
173    $load[ $sys ][ "this" ][ "stats"   ] = ProcStats( $sys );
174    $load[ $sys ][ "this" ][ "sum"     ] = array_sum( $load[ $sys ][ "this" ][ "stats" ][ "cpu" ] );
175    $load[ $sys ][ "this" ][ "sum012"  ] = array_sum( array_slice( $load[ $sys ][ "this" ][ "stats" ][ "cpu" ], 0, 3  ) );
176
177    if ( !$init ) {
178        $total = $load[ $sys ][ "this" ][ "sum" ] - $load[ $sys ][ "prev" ][ "sum" ];
179
180        $load[ $sys ][ "this" ][ "load" ] = round( 100 *
181                                                      ( $load[ $sys ][ "this" ][ "sum012" ] -
182                                                        $load[ $sys ][ "prev" ][ "sum012" ] )
183                                                      / $total, 2 );
184
185        $load[ $sys ][ "this" ][ "iowait"  ] = round( 100 *
186                                                      ( $load[ $sys ][ "this" ][ "stats" ][ "cpu" ][ 4 ] -
187                                                        $load[ $sys ][ "prev" ][ "stats" ][ "cpu" ][ 4 ] )
188                                                      / $total, 2 );
189
190        foreach ( $load[ $sys ][ "this" ][ "stats" ][ "net" ] as $k => $v ) {
191            $load[ $sys ][ "this" ][ "net" ][ $k ] = ( $v - $load[ $sys ][ "prev" ][ "stats" ][ "net" ][ $k ] ) * 1e-6;
192        }
193    }
194
195    $load[ $sys ][ "this" ][ "memused" ] = $load[ $sys ][ "this" ][ "stats" ][ "mem" ][ "memused" ];
196    $load[ $sys ][ "this" ][ "swapused" ] = $load[ $sys ][ "this" ][ "stats" ][ "mem" ][ "swapused" ];
197
198//    echo "prev: " . print_r( $load[ $sys ][ "prev" ], true ) . "\n";
199//    echo "this: " . print_r( $load[ $sys ][ "this" ], true ) . "\n";
200   
201}
202
203$allresources = array_keys( (array) $appconfig->resources );
204
205$plotdata =
206    array(
207        "jobhistory" =>
208        array( "options" =>
209               array(
210                   "xtics" => array()
211               )
212               ,"data" =>
213               array(
214                   array(
215                       "lines" => array( "show" => "true", "fill" => "true", "zero" => "true" )
216                       ,"data"  => array()
217                   )
218               )
219        )
220        ,"load" =>
221        array( "options" =>
222               array(
223                   "xtics" => array()
224                   ,"ymax" => 100
225                   ,"legend" =>
226                   array(
227                       "container" => "true"
228                       ,"backgroundOpacity" => 0.95
229                   )
230               )
231               ,"data" => array()
232        )
233        ,"iowait" =>
234        array( "options" =>
235               array(
236                   "xtics" => array()
237                   ,"ymax" => 100
238                   ,"legend" =>
239                   array(
240                       "container" => "true"
241                       ,"backgroundOpacity" => 0.95
242                   )
243               )
244               ,"data" => array()
245        )
246        ,"memused" =>
247        array( "options" =>
248               array(
249                   "xtics" => array()
250                   ,"ymax" => 100
251                   ,"legend" =>
252                   array(
253                       "container" => "true"
254                       ,"backgroundOpacity" => 0.95
255                   )
256               )
257               ,"data" => array()
258        )
259        ,"swapused" =>
260        array( "options" =>
261               array(
262                   "xtics" => array()
263                   ,"ymax" => 100
264                   ,"legend" =>
265                   array(
266                       "container" => "true"
267                       ,"backgroundOpacity" => 0.95
268                   )
269               )
270               ,"data" => array()
271        )
272        ,"net" =>
273        array( "options" =>
274               array(
275                   "xtics" => array()
276                   ,"legend" =>
277                   array(
278                       "container" => "true"
279                       ,"noColumns" => 3
280                       ,"backgroundOpacity" => 0.95
281                   )
282               )
283               ,"data" => array()
284        )
285    );
286
287
288// init load data
289foreach ( $allresources as $v ) {
290    foreach ( array( "load", "iowait", "memused", "swapused" ) as $v2 ) {
291        $plotdata[ $v2 ][ "data" ][] =
292            array(
293                "lines" => array( "show" => "true", "fill" => "true", "zero" => "true" )
294                ,"label" => $v
295                ,"data"  => array()
296            );
297    }
298}
299
300// need special init for "net" as each has its own set of if
301
302function get_procstats( $init = false ) {
303    global $load;
304    global $allresources;
305    global $plotdata;
306
307    if ( $init ) {
308        $load = [];
309        foreach ( $allresources as $v ) {
310            $load[ $v ] = array( "this" => array() );
311        }
312    }
313
314    foreach ( $allresources as $v ) {
315        UpdateStats( $v, $init );
316    }
317
318
319    if ( $init ) {
320        foreach ( $allresources as $v ) {
321            foreach ( $load[ $v ][ "this" ][ "stats" ][ "net" ] as $k2 => $v2 ) {
322                $plotdata[ "net" ][ "data" ][] =
323                    array(
324                        "lines" => array( "show" => "true", "fill" => "true", "zero" => "true" )
325                        ,"label" => "$v-$k2"
326                        ,"data"  => array()
327                        ,"sys"   => $v
328                        ,"if"    => $k2
329                    );
330            }
331        }
332    }
333
334    // __~debug:jobmonitor{error_log( "get_procstats load[]:\n" . print_r( $load, true ) , 3, "/tmp/mylog" );}
335    // __~debug:jobmonitor{error_log( "get_procstats plotdata[]:\n" . print_r( $plotdata, true ) , 3, "/tmp/mylog" );}
336}   
337
338// get_runinfo populates runinfo array with job info
339// to get more data => add it to the runinfo
340
341function get_runinfo( $error_json_exit = false ) {
342   global $use_db;
343   global $db_errors;
344   global $appconfig;
345   global $runinfo;
346   global $nowsecs;
347   global $startsecs;
348   global $plotdata;
349   global $load;
350   global $allresources;
351   global $interval;
352
353   $runinfo = [];
354
355   if ( !db_connect( $error_json_exit ) )
356   {
357       return false;
358   }
359
360   $runs = $use_db->__application__->running->find();
361
362   $nowsecs = microtime( true );
363
364   get_procstats();
365
366   foreach ( $runs as $v ) {
367       $uuid = $v['_id'];
368       $job = $use_db->__application__->jobs->findOne( array( "_id" => $uuid ) );
369       $pids = $v['pid'];
370
371       $resources = [];
372
373       foreach ( $pids as $k2 => $v2 ) {
374           $resources[ $v2['where'] ] = true;
375           // later get pid info
376           // echo "   where: " . $v2['where'] . " pid: " . $v2['pid'] . " what: " . $v2['what'] . "\n";
377           // $cmd = $appconfig->resources->{ $v2['where'] } . " ps --ppid " . $v2['pid'];
378           // echo " cmd $cmd\n";
379       }
380
381       
382       if ( isset( $job["start"] ) ) {
383           $duration = floatval( $nowsecs - $job["start"]->sec );
384           $duration_s = sprintf( $duration > 1 * 60 ? "%.0f" : "%.1f", $duration - 60 * intval( $duration / 60 ) );
385           $duration_m = intval( $duration / 60 ) % 60;
386           $duration_h = intval( $duration /(60 * 60 ) ) % 24;
387           $duration_d = intval( $duration /(24 * 60 * 60 ) );
388           
389           $duration = "start";
390
391           $duration = ( $duration_d > 0 ? $duration_d . "d" : "" ) .
392               ( $duration_h > 0 ? $duration_h . "h" : "" ) .
393               ( $duration_m > 0 ? $duration_m . "m" : "" ) .
394               ( $duration_s > 0 ? $duration_s . "s" : "" );
395       } else {
396           $duration = "active";
397       }
398
399
400       $runinfo[] =
401           array(
402               "module"    => $job[ 'module' ]
403               ,"user"      => $job[ 'user' ]
404#               "pids"      => $v  [ 'pid' ]
405               ,"started"   => date( "Y M d H:i:s T",$job["start"]->sec )
406               ,"duration"  => $duration
407               ,"resources" => implode( ",", array_keys( $resources ) )
408               ,"id"        => $uuid
409           );
410   }
411   $thissecs = round( $nowsecs - $startsecs, 3 );
412
413   $plotdata[ "jobhistory" ][ "data" ][0][ "data" ][] = array( $thissecs, count( $runinfo ) );
414   $plotdata[ "jobhistory" ][ "data" ][0][ "data" ] =
415       array_slice(
416           $plotdata[ "jobhistory" ][ "data" ][0][ "data" ],
417           -$GLOBALS[ 'maxplottimes' ] );
418
419   foreach ( $plotdata[ "load" ][ "data" ] as $k => $v ) {
420       // __~debug:jobmonitor{error_log( "load key\n" . $plotdata[ "load" ][ "data" ][ $k ][ "label" ] . "\n", 3, "/tmp/mylog" );}
421       // __~debug:jobmonitor{error_log( "load value\n" . $load[ $plotdata[ "load" ][ "data" ][ $k ][ "label" ]][ "this" ][ "load" ] . "\n", 3, "/tmp/mylog" );}
422       
423       $sys = $plotdata[ $v2 ][ "data" ][ $k ][ "label" ];
424       foreach ( array( "load", "iowait", "memused", "swapused" ) as $v2 ) {
425           $plotdata[ $v2 ][ "data" ][ $k ][ "data" ][] =
426               array( $thissecs, $load[ $sys ][ "this" ][ $v2 ] );
427           $plotdata[ $v2 ][ "data" ][ $k ][ "data" ] =
428               array_slice(
429                   $plotdata[ $v2 ][ "data" ][ $k ][ "data" ],
430                   -$GLOBALS[ 'maxplottimes' ] );
431
432       }
433       // __~debug:jobmonitor{error_log( "load data k $k\n" . print_r( $plotdata[ "load" ][ "data" ][ $k ][ "data" ], true )  . "\n", 3, "/tmp/mylog" );}
434
435   }
436
437   foreach ( $plotdata[ "net" ][ "data" ] as $k => $v ) {
438       $sys = $plotdata[ "net" ][ "data" ][ $k ][ "sys" ];
439       $if  = $plotdata[ "net" ][ "data" ][ $k ][ "if" ];
440
441       $plotdata[ "net" ][ "data" ][ $k ][ "data" ][] =
442           array( $thissecs, $load[ $sys ][ "this" ][ "net" ][ $if ] / $interval );
443       $plotdata[ "net" ][ "data" ][ $k ][ "data" ] =
444           array_slice(
445               $plotdata[ "net" ][ "data" ][ $k ][ "data" ],
446               -$GLOBALS[ 'maxplottimes' ] );
447   }
448
449   $ymaxa = [];
450   $xticsfull = [];
451   foreach ( $plotdata[ "jobhistory" ][ "data" ][0][ "data" ] as $k => $v ) {
452       $ymaxa[] = $v[ 1 ];
453       $xticsfull[] = array( $v[ 0 ], date( "H:i:s", $v[ 0 ] + $startsecs ) );
454   }
455
456   // __~debug:jobmonitor{error_log( "xticsfull[]:\n" . print_r( $xticsfull, true ) , 3, "/tmp/mylog" );}
457
458//   $xtics = [];
459   $xticsc = count( $xticsfull );
460   if ( $xticsc > $GLOBALS[ 'maxxticsvis' ] ) {
461       $addtics = 0;
462       if ( $xticsc > $GLOBALS[ 'xminplottime' ] ) {
463           $addtics = ( $xticsc - $GLOBALS[ 'xminplottime' ] ) * $GLOBALS[ 'maxxticsvis' ] / $GLOBALS[ 'xminplottime' ];
464       }
465       $each = round( $xticsc / ( $addtics + $GLOBALS[ 'maxxticsvis' ] ) );
466       for ( $i = 0; $i < $xticsc; ++$i ) {
467           if ( $i % $each ) {
468               $xticsfull[ $i ][ 1 ] = "";
469           }
470       }
471   }
472   
473//   __~debug:jobmonitor{error_log( "xtics[]:\n" . print_r( $xtics, true ) , 3, "/tmp/mylog" );}
474
475 //   __~debug:jobmonitor{error_log( "xticsfull[] after trim:\n" . print_r( $xticsfull, true ) , 3, "/tmp/mylog" );}
476
477   $plotdata[ "jobhistory" ][ "options" ][ "ymax" ] = max( $ymaxa ) + 1;
478
479   $useminplottime = 0;
480   if ( $xticsc > $GLOBALS[ 'xminplottime' ] ) {
481       $useminplottime = $plotdata[ "jobhistory" ][ "data" ][0][ "data" ][ $xticsc - $GLOBALS[ 'xminplottime' ] ][ 0 ];
482   }
483
484   foreach ( $plotdata as $k => $v ) {
485       $plotdata[ $k ][ "options" ][ "xtics" ] = $xticsfull;
486       $plotdata[ $k ][ "options" ][ "xmin"  ] = $useminplottime;
487   }
488
489   return true;
490}
491
492function get_html_runinfo( $error_json_exit = false ) {
493    global $runinfo;
494    global $html_runinfo;
495
496    $html_runinfo = "No jobs running";
497   
498    if ( !get_runinfo( $error_json_exit ) ) {
499        return false;
500    }
501
502    if ( !count( $runinfo ) ) {
503        return true;
504    }
505   
506    $html_runinfo = "<table><tr><th>" . implode( "</th><th>", array_keys( $runinfo[ 0 ] ) ) . "</th></tr>";
507
508    foreach ( $runinfo as $k => $v ) {
509        $html_runinfo .= "<tr><td>" . implode( "</td><td>",  $v ) . "</td></tr>";
510    }       
511
512    $html_runinfo .= "</table>";
513}
514
515$results = [];
516$results[ '_uuid' ] = $_REQUEST[ '_uuid' ];
517$startsecs = microtime( true );
518
519$GLOBALS[ 'maxplottimes' ] = 240;
520$GLOBALS[ 'xminplottime' ] = intval( $GLOBALS[ 'maxplottimes' ] / 3 );
521$GLOBALS[ 'maxxticsvis' ] = 4;
522
523get_procstats( true );
524sleep( 1 );
525
526// run until cancelled
527
528$interval = $_REQUEST[ 'interval' ];
529
530// for ( $i = 0; $i < 3; ++$i ) {
531do {
532    $nowsecs = microtime( true );
533    get_html_runinfo( true );
534
535    $results[ "monitordata" ] = "<p>Last refreshed " . date( "Y M d H:i:s T", $nowsecs ) . "</p>" .  $html_runinfo;
536
537    foreach ( $plotdata as $k => $v ) {
538        $results[ $k ] = $v;
539    }
540    // __~debug:jobmonitor{error_log( print_r( $results, true ) , 3, "/tmp/mylog" );}
541    // __~debug:jobmonitor{error_log( json_encode( $results ) . "\n", 3, "/tmp/mylog" );}
542    $zmq_socket->send( json_encode( $results ) );
543    sleep( $interval );
544} while(1);
545
546
547echo '{"_none":"1"}';
548
549?>
Note: See TracBrowser for help on using the repository browser.