summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sapi/fpm/fpm/fpm_main.c12
-rw-r--r--sapi/fpm/fpm/fpm_status.c99
-rw-r--r--sapi/fpm/fpm/fpm_status.h1
-rw-r--r--sapi/fpm/tests/025.phpt132
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);
+?>