Skip to content

Commit 140def4

Browse files
Till Backhausbukka
authored andcommitted
Implement fpm_get_status
1 parent b585f04 commit 140def4

File tree

4 files changed

+243
-1
lines changed

4 files changed

+243
-1
lines changed

sapi/fpm/fpm/fpm_main.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1566,8 +1566,20 @@ PHP_FUNCTION(apache_request_headers) /* {{{ */
15661566
}
15671567
} /* }}} */
15681568

1569+
/* {{{ proto array fpm_get_status
1570+
* Returns the status of the fastcgi process manager */
1571+
PHP_FUNCTION(fpm_get_status) /* {{{ */
1572+
{
1573+
int error = fpm_status_export_to_zval(return_value);
1574+
if(error){
1575+
RETURN_FALSE;
1576+
}
1577+
}
1578+
/* }}} */
1579+
15691580
static const zend_function_entry cgi_fcgi_sapi_functions[] = {
15701581
PHP_FE(fastcgi_finish_request, cgi_fcgi_sapi_no_arginfo)
1582+
PHP_FE(fpm_get_status, NULL)
15711583
PHP_FE(apache_request_headers, cgi_fcgi_sapi_no_arginfo)
15721584
PHP_FALIAS(getallheaders, apache_request_headers, cgi_fcgi_sapi_no_arginfo)
15731585
PHP_FE_END

sapi/fpm/fpm/fpm_status.c

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
/* (c) 2009 Jerome Loyet */
44

55
#include "php.h"
6+
#include "zend_long.h"
67
#include "SAPI.h"
78
#include <stdio.h>
89

@@ -45,6 +46,103 @@ int fpm_status_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
4546
}
4647
/* }}} */
4748

49+
int fpm_status_export_to_zval(zval *status)
50+
{
51+
struct fpm_scoreboard_s scoreboard, *scoreboard_p;
52+
zval fpm_proc_stats, fpm_proc_stat;
53+
time_t now_epoch;
54+
struct timeval duration, now;
55+
double cpu;
56+
int i;
57+
58+
59+
scoreboard_p = fpm_scoreboard_acquire(NULL, 1);
60+
if (!scoreboard_p) {
61+
zlog(ZLOG_NOTICE, "[pool %s] status: scoreboard already in use.", scoreboard_p->pool);
62+
return -1;
63+
}
64+
65+
/* copy the scoreboard not to bother other processes */
66+
scoreboard = *scoreboard_p;
67+
struct fpm_scoreboard_proc_s procs[scoreboard.nprocs];
68+
69+
struct fpm_scoreboard_proc_s *proc_p;
70+
for(i=0; i<scoreboard.nprocs; i++) {
71+
proc_p = fpm_scoreboard_proc_acquire(scoreboard_p, i, 1);
72+
if (!proc_p){
73+
procs[i].used=-1;
74+
continue;
75+
}
76+
procs[i] = *proc_p;
77+
fpm_scoreboard_proc_release(proc_p);
78+
}
79+
fpm_scoreboard_release(scoreboard_p);
80+
81+
now_epoch = time(NULL);
82+
fpm_clock_get(&now);
83+
84+
array_init(status);
85+
add_assoc_string(status, "pool", scoreboard.pool);
86+
add_assoc_string(status, "process-manager", PM2STR(scoreboard.pm));
87+
add_assoc_long(status, "start-time", scoreboard.start_epoch);
88+
add_assoc_long(status, "start-since", now_epoch - scoreboard.start_epoch);
89+
add_assoc_long(status, "accepted-conn", scoreboard.requests);
90+
#ifdef HAVE_FPM_LQ
91+
add_assoc_long(status, "listen-queue", scoreboard.lq);
92+
add_assoc_long(status, "max-listen-queue", scoreboard.lq_max);
93+
add_assoc_long(status, "listen-queue-len", scoreboard.lq_len);
94+
#endif
95+
add_assoc_long(status, "idle-processes", scoreboard.idle);
96+
add_assoc_long(status, "active-processes", scoreboard.active);
97+
add_assoc_long(status, "total-processes", scoreboard.idle + scoreboard.active);
98+
add_assoc_long(status, "max-active-processes", scoreboard.active_max);
99+
add_assoc_long(status, "max-children-reached", scoreboard.max_children_reached);
100+
add_assoc_long(status, "slow-requests", scoreboard.slow_rq);
101+
102+
array_init(&fpm_proc_stats);
103+
for(i=0; i<scoreboard.nprocs; i++) {
104+
if (!procs[i].used) {
105+
continue;
106+
}
107+
proc_p = &procs[i];
108+
#ifdef HAVE_FPM_LQ
109+
/* prevent NaN */
110+
if (procs[i].cpu_duration.tv_sec == 0 && procs[i].cpu_duration.tv_usec == 0) {
111+
cpu = 0.;
112+
} else {
113+
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.;
114+
}
115+
#endif
116+
117+
array_init(&fpm_proc_stat);
118+
add_assoc_long(&fpm_proc_stat, "pid", procs[i].pid);
119+
add_assoc_string(&fpm_proc_stat, "state", fpm_request_get_stage_name(procs[i].request_stage));
120+
add_assoc_long(&fpm_proc_stat, "start-time", procs[i].start_epoch);
121+
add_assoc_long(&fpm_proc_stat, "start-since", now_epoch - procs[i].start_epoch);
122+
add_assoc_long(&fpm_proc_stat, "requests", procs[i].requests);
123+
if (procs[i].request_stage == FPM_REQUEST_ACCEPTING) {
124+
duration = procs[i].duration;
125+
} else {
126+
timersub(&now, &procs[i].accepted, &duration);
127+
}
128+
add_assoc_long(&fpm_proc_stat, "request-duration", duration.tv_sec * 1000000UL + duration.tv_usec);
129+
add_assoc_string(&fpm_proc_stat, "request-method", procs[i].request_method[0] != '\0' ? procs[i].request_method : "-");
130+
add_assoc_string(&fpm_proc_stat, "request-uri", procs[i].request_uri);
131+
add_assoc_string(&fpm_proc_stat, "query-string", procs[i].query_string);
132+
add_assoc_long(&fpm_proc_stat, "request-length", procs[i].content_length);
133+
add_assoc_string(&fpm_proc_stat, "user", procs[i].auth_user[0] != '\0' ? procs[i].auth_user : "-");
134+
add_assoc_string(&fpm_proc_stat, "script", procs[i].script_filename[0] != '\0' ? procs[i].script_filename : "-");
135+
#ifdef HAVE_FPM_LQ
136+
add_assoc_double(&fpm_proc_stat, "last-request-cpu", procs[i].request_stage == FPM_REQUEST_ACCEPTING ? cpu : 0.);
137+
#endif
138+
add_assoc_long(&fpm_proc_stat, "last-request-memory", procs[i].request_stage == FPM_REQUEST_ACCEPTING ? procs[i].memory : 0);
139+
add_next_index_zval(&fpm_proc_stats, &fpm_proc_stat);
140+
}
141+
add_assoc_zval(status, "procs", &fpm_proc_stats);
142+
return 0;
143+
}
144+
/* }}} */
145+
48146
int fpm_status_handle_request(void) /* {{{ */
49147
{
50148
struct fpm_scoreboard_s scoreboard, *scoreboard_p;
@@ -478,4 +576,3 @@ int fpm_status_handle_request(void) /* {{{ */
478576
return 0;
479577
}
480578
/* }}} */
481-

sapi/fpm/fpm/fpm_status.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ void fpm_status_increment_accepted_conn(struct fpm_shm_s *shm);
2828
void fpm_status_set_pm(struct fpm_shm_s *shm, int pm);
2929
void fpm_status_update_max_children_reached(struct fpm_shm_s *shm, unsigned int max_children_reached);
3030
void fpm_status_increment_max_children_reached(struct fpm_shm_s *shm);
31+
int fpm_status_export_to_zval(zval *status);
3132
int fpm_status_handle_request(void);
3233

3334
extern struct fpm_shm_s *fpm_status_shm;

sapi/fpm/tests/025.phpt

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
--TEST--
2+
FPM: Test fpm_get_status function
3+
--SKIPIF--
4+
<?php include "skipif.inc"; ?>
5+
--FILE--
6+
<?php
7+
8+
include "include.inc";
9+
10+
$logfile = __DIR__.'/php-fpm.log.tmp';
11+
$srcfile = __DIR__.'/php-fpm.tmp.php';
12+
$port = 9000+PHP_INT_SIZE;
13+
14+
$cfg = <<<EOT
15+
[global]
16+
error_log = $logfile
17+
[unconfined]
18+
listen = 127.0.0.1:$port
19+
pm = dynamic
20+
pm.max_children = 5
21+
pm.start_servers = 1
22+
pm.min_spare_servers = 1
23+
pm.max_spare_servers = 3
24+
EOT;
25+
26+
$code = <<<EOT
27+
<?php
28+
echo "Test Start\n";
29+
var_dump(fpm_get_status());
30+
echo "Test End\n";
31+
EOT;
32+
file_put_contents($srcfile, $code);
33+
34+
$fpm = run_fpm($cfg, $tail);
35+
if (is_resource($fpm)) {
36+
fpm_display_log($tail, 2);
37+
try {
38+
$req = run_request('127.0.0.1', $port, $srcfile);
39+
echo strstr($req, "Test Start");
40+
echo "Request ok\n";
41+
} catch (Exception $e) {
42+
echo "Request error\n";
43+
}
44+
proc_terminate($fpm);
45+
fpm_display_log($tail, -1);
46+
fclose($tail);
47+
proc_close($fpm);
48+
}
49+
50+
?>
51+
Done
52+
--EXPECTF--
53+
[%s] NOTICE: fpm is running, pid %d
54+
[%s] NOTICE: ready to handle connections
55+
Test Start
56+
array(15) {
57+
["pool"]=>
58+
string(10) "unconfined"
59+
["process-manager"]=>
60+
string(7) "dynamic"
61+
["start-time"]=>
62+
int(%d)
63+
["start-since"]=>
64+
int(%d)
65+
["accepted-conn"]=>
66+
int(1)
67+
["listen-queue"]=>
68+
int(0)
69+
["max-listen-queue"]=>
70+
int(0)
71+
["listen-queue-len"]=>
72+
int(128)
73+
["idle-processes"]=>
74+
int(0)
75+
["active-processes"]=>
76+
int(1)
77+
["total-processes"]=>
78+
int(1)
79+
["max-active-processes"]=>
80+
int(1)
81+
["max-children-reached"]=>
82+
int(0)
83+
["slow-requests"]=>
84+
int(0)
85+
["procs"]=>
86+
array(1) {
87+
[0]=>
88+
array(14) {
89+
["pid"]=>
90+
int(%d)
91+
["state"]=>
92+
string(7) "Running"
93+
["start-time"]=>
94+
int(%d)
95+
["start-since"]=>
96+
int(%d)
97+
["requests"]=>
98+
int(1)
99+
["request-duration"]=>
100+
int(%d)
101+
["request-method"]=>
102+
string(3) "GET"
103+
["request-uri"]=>
104+
string(%d) "%s"
105+
["query-string"]=>
106+
string(0) ""
107+
["request-length"]=>
108+
int(0)
109+
["user"]=>
110+
string(1) "-"
111+
["script"]=>
112+
string(%d) "%s"
113+
["last-request-cpu"]=>
114+
float(0)
115+
["last-request-memory"]=>
116+
int(0)
117+
}
118+
}
119+
}
120+
Test End
121+
122+
Request ok
123+
[%s] NOTICE: Terminating ...
124+
[%s] NOTICE: exiting, bye-bye!
125+
Done
126+
--CLEAN--
127+
<?php
128+
$logfile = __DIR__.'/php-fpm.log.tmp';
129+
$srcfile = __DIR__.'/php-fpm.tmp.php';
130+
@unlink($logfile);
131+
@unlink($srcfile);
132+
?>

0 commit comments

Comments
 (0)