diff options
| -rw-r--r-- | sapi/fpm/fpm/fpm_main.c | 12 | ||||
| -rw-r--r-- | sapi/fpm/fpm/fpm_status.c | 99 | ||||
| -rw-r--r-- | sapi/fpm/fpm/fpm_status.h | 1 | ||||
| -rw-r--r-- | sapi/fpm/tests/025.phpt | 132 |
4 files changed, 243 insertions, 1 deletions
diff --git a/sapi/fpm/fpm/fpm_main.c b/sapi/fpm/fpm/fpm_main.c index e815be4700..673ae447b4 100644 --- a/sapi/fpm/fpm/fpm_main.c +++ b/sapi/fpm/fpm/fpm_main.c @@ -1566,8 +1566,20 @@ PHP_FUNCTION(apache_request_headers) /* {{{ */ } } /* }}} */ +/* {{{ 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; + } +} +/* }}} */ + static const zend_function_entry cgi_fcgi_sapi_functions[] = { PHP_FE(fastcgi_finish_request, cgi_fcgi_sapi_no_arginfo) + PHP_FE(fpm_get_status, NULL) PHP_FE(apache_request_headers, cgi_fcgi_sapi_no_arginfo) PHP_FALIAS(getallheaders, apache_request_headers, cgi_fcgi_sapi_no_arginfo) PHP_FE_END diff --git a/sapi/fpm/fpm/fpm_status.c b/sapi/fpm/fpm/fpm_status.c index a8cfb3fa49..2df0714409 100644 --- a/sapi/fpm/fpm/fpm_status.c +++ b/sapi/fpm/fpm/fpm_status.c @@ -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++) { + 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; } /* }}} */ - diff --git a/sapi/fpm/fpm/fpm_status.h b/sapi/fpm/fpm/fpm_status.h index c6c27cd031..79caf694cc 100644 --- a/sapi/fpm/fpm/fpm_status.h +++ b/sapi/fpm/fpm/fpm_status.h @@ -28,6 +28,7 @@ void fpm_status_increment_accepted_conn(struct fpm_shm_s *shm); void fpm_status_set_pm(struct fpm_shm_s *shm, int pm); void fpm_status_update_max_children_reached(struct fpm_shm_s *shm, unsigned int max_children_reached); void fpm_status_increment_max_children_reached(struct fpm_shm_s *shm); +int fpm_status_export_to_zval(zval *status); int fpm_status_handle_request(void); extern struct fpm_shm_s *fpm_status_shm; diff --git a/sapi/fpm/tests/025.phpt b/sapi/fpm/tests/025.phpt new file mode 100644 index 0000000000..c3bd388db6 --- /dev/null +++ b/sapi/fpm/tests/025.phpt @@ -0,0 +1,132 @@ +--TEST-- +FPM: Test fpm_get_status function +--SKIPIF-- +<?php include "skipif.inc"; ?> +--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); +?> |
