-
Notifications
You must be signed in to change notification settings - Fork 7.9k
WIP: Implement function to get fpm status from php fastcgi_get_status
#3182
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1547,8 +1547,21 @@ PHP_FUNCTION(fastcgi_finish_request) /* {{{ */ | |
} | ||
/* }}} */ | ||
|
||
/* {{{ proto array fpm_get_status | ||
* Returns the status of the fastcgi process manager */ | ||
PHP_FUNCTION(fpm_get_status) /* {{{ */ | ||
{ | ||
int error = fpm_status_export_to_zval(return_value); | ||
if(error){ | ||
RETURN_FALSE; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you should verbose this error There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I will do that |
||
} | ||
} | ||
/* }}} */ | ||
|
||
|
||
static const zend_function_entry cgi_fcgi_sapi_functions[] = { | ||
PHP_FE(fastcgi_finish_request, NULL) | ||
PHP_FE(fpm_get_status, NULL) | ||
PHP_FE_END | ||
}; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
/* (c) 2009 Jerome Loyet */ | ||
|
||
#include "php.h" | ||
#include "zend_long.h" | ||
#include "SAPI.h" | ||
#include <stdio.h> | ||
|
||
|
@@ -45,6 +46,103 @@ int fpm_status_init_child(struct fpm_worker_pool_s *wp) /* {{{ */ | |
} | ||
/* }}} */ | ||
|
||
int fpm_status_export_to_zval(zval *status) | ||
{ | ||
struct fpm_scoreboard_s scoreboard, *scoreboard_p; | ||
zval fpm_proc_stats, fpm_proc_stat; | ||
time_t now_epoch; | ||
struct timeval duration, now; | ||
double cpu; | ||
int i; | ||
|
||
|
||
scoreboard_p = fpm_scoreboard_acquire(NULL, 1); | ||
if (!scoreboard_p) { | ||
zlog(ZLOG_NOTICE, "[pool %s] status: scoreboard already in use.", scoreboard_p->pool); | ||
return -1; | ||
} | ||
|
||
/* copy the scoreboard not to bother other processes */ | ||
scoreboard = *scoreboard_p; | ||
struct fpm_scoreboard_proc_s procs[scoreboard.nprocs]; | ||
|
||
struct fpm_scoreboard_proc_s *proc_p; | ||
for(i=0; i<scoreboard.nprocs; i++) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cs: for () {} |
||
proc_p = fpm_scoreboard_proc_acquire(scoreboard_p, i, 1); | ||
if (!proc_p){ | ||
procs[i].used=-1; | ||
continue; | ||
} | ||
procs[i] = *proc_p; | ||
fpm_scoreboard_proc_release(proc_p); | ||
} | ||
fpm_scoreboard_release(scoreboard_p); | ||
|
||
now_epoch = time(NULL); | ||
fpm_clock_get(&now); | ||
|
||
array_init(status); | ||
add_assoc_string(status, "pool", scoreboard.pool); | ||
add_assoc_string(status, "process-manager", PM2STR(scoreboard.pm)); | ||
add_assoc_long(status, "start-time", scoreboard.start_epoch); | ||
add_assoc_long(status, "start-since", now_epoch - scoreboard.start_epoch); | ||
add_assoc_long(status, "accepted-conn", scoreboard.requests); | ||
#ifdef HAVE_FPM_LQ | ||
add_assoc_long(status, "listen-queue", scoreboard.lq); | ||
add_assoc_long(status, "max-listen-queue", scoreboard.lq_max); | ||
add_assoc_long(status, "listen-queue-len", scoreboard.lq_len); | ||
#endif | ||
add_assoc_long(status, "idle-processes", scoreboard.idle); | ||
add_assoc_long(status, "active-processes", scoreboard.active); | ||
add_assoc_long(status, "total-processes", scoreboard.idle + scoreboard.active); | ||
add_assoc_long(status, "max-active-processes", scoreboard.active_max); | ||
add_assoc_long(status, "max-children-reached", scoreboard.max_children_reached); | ||
add_assoc_long(status, "slow-requests", scoreboard.slow_rq); | ||
|
||
array_init(&fpm_proc_stats); | ||
for(i=0; i<scoreboard.nprocs; i++) { | ||
if (!procs[i].used) { | ||
continue; | ||
} | ||
proc_p = &procs[i]; | ||
#ifdef HAVE_FPM_LQ | ||
/* prevent NaN */ | ||
if (procs[i].cpu_duration.tv_sec == 0 && procs[i].cpu_duration.tv_usec == 0) { | ||
cpu = 0.; | ||
} else { | ||
cpu = (procs[i].last_request_cpu.tms_utime + procs[i].last_request_cpu.tms_stime + procs[i].last_request_cpu.tms_cutime + procs[i].last_request_cpu.tms_cstime) / fpm_scoreboard_get_tick() / (procs[i].cpu_duration.tv_sec + procs[i].cpu_duration.tv_usec / 1000000.) * 100.; | ||
} | ||
#endif | ||
|
||
array_init(&fpm_proc_stat); | ||
add_assoc_long(&fpm_proc_stat, "pid", procs[i].pid); | ||
add_assoc_string(&fpm_proc_stat, "state", fpm_request_get_stage_name(procs[i].request_stage)); | ||
add_assoc_long(&fpm_proc_stat, "start-time", procs[i].start_epoch); | ||
add_assoc_long(&fpm_proc_stat, "start-since", now_epoch - procs[i].start_epoch); | ||
add_assoc_long(&fpm_proc_stat, "requests", procs[i].requests); | ||
if (procs[i].request_stage == FPM_REQUEST_ACCEPTING) { | ||
duration = procs[i].duration; | ||
} else { | ||
timersub(&now, &procs[i].accepted, &duration); | ||
} | ||
add_assoc_long(&fpm_proc_stat, "request-duration", duration.tv_sec * 1000000UL + duration.tv_usec); | ||
add_assoc_string(&fpm_proc_stat, "request-method", procs[i].request_method[0] != '\0' ? procs[i].request_method : "-"); | ||
add_assoc_string(&fpm_proc_stat, "request-uri", procs[i].request_uri); | ||
add_assoc_string(&fpm_proc_stat, "query-string", procs[i].query_string); | ||
add_assoc_long(&fpm_proc_stat, "request-length", procs[i].content_length); | ||
add_assoc_string(&fpm_proc_stat, "user", procs[i].auth_user[0] != '\0' ? procs[i].auth_user : "-"); | ||
add_assoc_string(&fpm_proc_stat, "script", procs[i].script_filename[0] != '\0' ? procs[i].script_filename : "-"); | ||
#ifdef HAVE_FPM_LQ | ||
add_assoc_double(&fpm_proc_stat, "last-request-cpu", procs[i].request_stage == FPM_REQUEST_ACCEPTING ? cpu : 0.); | ||
#endif | ||
add_assoc_long(&fpm_proc_stat, "last-request-memory", procs[i].request_stage == FPM_REQUEST_ACCEPTING ? procs[i].memory : 0); | ||
add_next_index_zval(&fpm_proc_stats, &fpm_proc_stat); | ||
} | ||
add_assoc_zval(status, "procs", &fpm_proc_stats); | ||
return 0; | ||
} | ||
/* }}} */ | ||
|
||
int fpm_status_handle_request(void) /* {{{ */ | ||
{ | ||
struct fpm_scoreboard_s scoreboard, *scoreboard_p; | ||
|
@@ -478,4 +576,3 @@ int fpm_status_handle_request(void) /* {{{ */ | |
return 0; | ||
} | ||
/* }}} */ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
--TEST-- | ||
FPM: Test fpm_get_status function | ||
--SKIPIF-- | ||
<?php include "skipif.inc"; ?> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
--FILE-- | ||
<?php | ||
|
||
include "include.inc"; | ||
|
||
$logfile = __DIR__.'/php-fpm.log.tmp'; | ||
$srcfile = __DIR__.'/php-fpm.tmp.php'; | ||
$port = 9000+PHP_INT_SIZE; | ||
|
||
$cfg = <<<EOT | ||
[global] | ||
error_log = $logfile | ||
[unconfined] | ||
listen = 127.0.0.1:$port | ||
pm = dynamic | ||
pm.max_children = 5 | ||
pm.start_servers = 1 | ||
pm.min_spare_servers = 1 | ||
pm.max_spare_servers = 3 | ||
EOT; | ||
|
||
$code = <<<EOT | ||
<?php | ||
echo "Test Start\n"; | ||
var_dump(fpm_get_status()); | ||
echo "Test End\n"; | ||
EOT; | ||
file_put_contents($srcfile, $code); | ||
|
||
$fpm = run_fpm($cfg, $tail); | ||
if (is_resource($fpm)) { | ||
fpm_display_log($tail, 2); | ||
try { | ||
$req = run_request('127.0.0.1', $port, $srcfile); | ||
echo strstr($req, "Test Start"); | ||
echo "Request ok\n"; | ||
} catch (Exception $e) { | ||
echo "Request error\n"; | ||
} | ||
proc_terminate($fpm); | ||
fpm_display_log($tail, -1); | ||
fclose($tail); | ||
proc_close($fpm); | ||
} | ||
|
||
?> | ||
Done | ||
--EXPECTF-- | ||
[%s] NOTICE: fpm is running, pid %d | ||
[%s] NOTICE: ready to handle connections | ||
Test Start | ||
array(15) { | ||
["pool"]=> | ||
string(10) "unconfined" | ||
["process-manager"]=> | ||
string(7) "dynamic" | ||
["start-time"]=> | ||
int(%d) | ||
["start-since"]=> | ||
int(%d) | ||
["accepted-conn"]=> | ||
int(1) | ||
["listen-queue"]=> | ||
int(0) | ||
["max-listen-queue"]=> | ||
int(0) | ||
["listen-queue-len"]=> | ||
int(128) | ||
["idle-processes"]=> | ||
int(0) | ||
["active-processes"]=> | ||
int(1) | ||
["total-processes"]=> | ||
int(1) | ||
["max-active-processes"]=> | ||
int(1) | ||
["max-children-reached"]=> | ||
int(0) | ||
["slow-requests"]=> | ||
int(0) | ||
["procs"]=> | ||
array(1) { | ||
[0]=> | ||
array(14) { | ||
["pid"]=> | ||
int(%d) | ||
["state"]=> | ||
string(7) "Running" | ||
["start-time"]=> | ||
int(%d) | ||
["start-since"]=> | ||
int(%d) | ||
["requests"]=> | ||
int(1) | ||
["request-duration"]=> | ||
int(%d) | ||
["request-method"]=> | ||
string(3) "GET" | ||
["request-uri"]=> | ||
string(%d) "%s" | ||
["query-string"]=> | ||
string(0) "" | ||
["request-length"]=> | ||
int(0) | ||
["user"]=> | ||
string(1) "-" | ||
["script"]=> | ||
string(%d) "%s" | ||
["last-request-cpu"]=> | ||
float(0) | ||
["last-request-memory"]=> | ||
int(0) | ||
} | ||
} | ||
} | ||
Test End | ||
|
||
Request ok | ||
[%s] NOTICE: Terminating ... | ||
[%s] NOTICE: exiting, bye-bye! | ||
Done | ||
--CLEAN-- | ||
<?php | ||
$logfile = __DIR__.'/php-fpm.log.tmp'; | ||
$srcfile = __DIR__.'/php-fpm.tmp.php'; | ||
@unlink($logfile); | ||
@unlink($srcfile); | ||
?> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CS: missing spaces... If you don't need to use
error
later then this should do: