19static char *fpm_status_uri =
NULL;
20static char *fpm_status_ping_uri =
NULL;
21static char *fpm_status_ping_response =
NULL;
27 zlog(
ZLOG_ERROR,
"unable to init fpm_status because conf structure is NULL");
51 zval fpm_proc_stats, fpm_proc_stat;
53 struct timeval duration,
now;
59 zlog(
ZLOG_NOTICE,
"[pool (unknown)] status: scoreboard already in use.");
64 scoreboard = *scoreboard_p;
69 for(i=0; i<scoreboard.
nprocs; i++) {
84 add_assoc_string(
status,
"pool", scoreboard.
pool);
85 add_assoc_string(
status,
"process-manager",
PM2STR(scoreboard.
pm));
89 add_assoc_long(
status,
"listen-queue", scoreboard.
lq);
90 add_assoc_long(
status,
"max-listen-queue", scoreboard.
lq_max);
91 add_assoc_long(
status,
"listen-queue-len", scoreboard.
lq_len);
92 add_assoc_long(
status,
"idle-processes", scoreboard.
idle);
93 add_assoc_long(
status,
"active-processes", scoreboard.
active);
94 add_assoc_long(
status,
"total-processes", scoreboard.
idle + scoreboard.
active);
101 for(i=0; i<scoreboard.
nprocs; i++) {
102 if (!procs[i].
used) {
107 if (procs[i].cpu_duration.tv_sec == 0 && procs[i].cpu_duration.tv_usec == 0) {
110 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 add_assoc_long(&fpm_proc_stat,
"pid", procs[i].
pid);
116 add_assoc_long(&fpm_proc_stat,
"start-time", procs[i].
start_epoch);
117 add_assoc_long(&fpm_proc_stat,
"start-since", now_epoch - procs[i].
start_epoch);
118 add_assoc_long(&fpm_proc_stat,
"requests", procs[i].
requests);
124 add_assoc_long(&fpm_proc_stat,
"request-duration",
duration.tv_sec * 1000000UL +
duration.tv_usec);
126 add_assoc_string(&fpm_proc_stat,
"request-uri", procs[i].
request_uri);
127 add_assoc_string(&fpm_proc_stat,
"query-string", procs[i].
query_string);
128 add_assoc_long(&fpm_proc_stat,
"request-length", procs[i].
content_length);
129 add_assoc_string(&fpm_proc_stat,
"user", procs[i].
auth_user[0] !=
'\0' ? procs[i].
auth_user :
"-");
130 add_assoc_string(&fpm_proc_stat,
"script", procs[i].script_filename[0] !=
'\0' ? procs[i].script_filename :
"-");
133 add_next_index_zval(&fpm_proc_stats, &fpm_proc_stat);
135 add_assoc_zval(
status,
"procs", &fpm_proc_stats);
146 char *
buffer, *time_format, time_buffer[64];
148 int full, has_start_time;
149 bool encode_html, encode_json;
150 char *short_syntax, *short_post;
151 char *full_pre, *full_syntax, *full_post, *full_separator;
158 if (fpm_status_ping_uri && fpm_status_ping_response && !
strcmp(fpm_status_ping_uri,
SG(request_info).
request_uri)) {
163 SG(sapi_headers).http_response_code = 200;
166 if (
SG(request_info).headers_only) {
170 PUTS(fpm_status_ping_response);
183 short_syntax = short_post =
NULL;
184 full_separator = full_pre = full_syntax = full_post =
NULL;
194 zlog(
ZLOG_ERROR,
"status: unable to find or access status shared memory");
195 SG(sapi_headers).http_response_code = 500;
199 PUTS(
"Internal error. Please review log file for errors.");
203 if (scoreboard_p->
idle < 0 || scoreboard_p->
active < 0) {
206 SG(sapi_headers).http_response_code = 500;
210 PUTS(
"Internal error. Please review log file for errors.");
217 SG(sapi_headers).http_response_code = 200;
220 if (
SG(request_info).headers_only) {
228 time_format =
"%d/%b/%Y:%H:%M:%S %z";
232 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"
233 "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
234 "<head><title>PHP-FPM Status Page</title></head>\n"
237 "<tr><th>pool</th><td>%s</td></tr>\n"
238 "<tr><th>process manager</th><td>%s</td></tr>\n"
239 "<tr><th>start time</th><td>%s</td></tr>\n"
240 "<tr><th>start since</th><td>%lu</td></tr>\n"
241 "<tr><th>accepted conn</th><td>%lu</td></tr>\n"
242 "<tr><th>listen queue</th><td>%d</td></tr>\n"
243 "<tr><th>max listen queue</th><td>%d</td></tr>\n"
244 "<tr><th>listen queue len</th><td>%u</td></tr>\n"
245 "<tr><th>idle processes</th><td>%d</td></tr>\n"
246 "<tr><th>active processes</th><td>%d</td></tr>\n"
247 "<tr><th>total processes</th><td>%d</td></tr>\n"
248 "<tr><th>max active processes</th><td>%d</td></tr>\n"
249 "<tr><th>max children reached</th><td>%u</td></tr>\n"
250 "<tr><th>slow requests</th><td>%lu</td></tr>\n"
251 "<tr><th>memory peak</th><td>%zu</td></tr>\n"
255 short_post =
"</body></html>";
258 "<table border=\"1\">\n"
262 "<th>start time</th>"
263 "<th>start since</th>"
265 "<th>request duration</th>"
266 "<th>request method</th>"
267 "<th>request uri</th>"
268 "<th>content length</th>"
271 "<th>last request cpu</th>"
272 "<th>last request memory</th>"
292 full_post =
"</table></body></html>";
302 "<?xml version=\"1.0\" ?>\n"
305 "<process-manager>%s</process-manager>\n"
306 "<start-time>%s</start-time>\n"
307 "<start-since>%lu</start-since>\n"
308 "<accepted-conn>%lu</accepted-conn>\n"
309 "<listen-queue>%d</listen-queue>\n"
310 "<max-listen-queue>%d</max-listen-queue>\n"
311 "<listen-queue-len>%u</listen-queue-len>\n"
312 "<idle-processes>%d</idle-processes>\n"
313 "<active-processes>%d</active-processes>\n"
314 "<total-processes>%d</total-processes>\n"
315 "<max-active-processes>%d</max-active-processes>\n"
316 "<max-children-reached>%u</max-children-reached>\n"
317 "<slow-requests>%lu</slow-requests>\n"
318 "<memory-peak>%zu</memory-peak>\n";
321 short_post =
"</status>";
323 full_pre =
"<processes>\n";
328 "<start-time>%s</start-time>"
329 "<start-since>%lu</start-since>"
330 "<requests>%lu</requests>"
331 "<request-duration>%lu</request-duration>"
332 "<request-method>%s</request-method>"
333 "<request-uri>%s%s%s</request-uri>"
334 "<content-length>%zu</content-length>"
336 "<script>%s</script>"
337 "<last-request-cpu>%.2f</last-request-cpu>"
338 "<last-request-memory>%zu</last-request-memory>"
341 full_post =
"</processes>\n</status>";
354 "\"process manager\":\"%s\","
356 "\"start since\":%lu,"
357 "\"accepted conn\":%lu,"
358 "\"listen queue\":%d,"
359 "\"max listen queue\":%d,"
360 "\"listen queue len\":%u,"
361 "\"idle processes\":%d,"
362 "\"active processes\":%d,"
363 "\"total processes\":%d,"
364 "\"max active processes\":%d,"
365 "\"max children reached\":%u,"
366 "\"slow requests\":%lu,"
367 "\"memory peak\":%zu";
372 full_separator =
",";
373 full_pre =
", \"processes\":[";
379 "\"start since\":%lu,"
381 "\"request duration\":%lu,"
382 "\"request method\":\"%s\","
383 "\"request uri\":\"%s%s%s\","
384 "\"content length\":%zu,"
387 "\"last request cpu\":%.2f,"
388 "\"last request memory\":%zu"
400 "# HELP phpfpm_up Could pool %s using a %s PM on PHP-FPM be reached?\n"
401 "# TYPE phpfpm_up gauge\n"
403 "# HELP phpfpm_start_since The number of seconds since FPM has started.\n"
404 "# TYPE phpfpm_start_since counter\n"
405 "phpfpm_start_since %lu\n"
406 "# HELP phpfpm_accepted_connections The number of requests accepted by the pool.\n"
407 "# TYPE phpfpm_accepted_connections counter\n"
408 "phpfpm_accepted_connections %lu\n"
409 "# HELP phpfpm_listen_queue The number of requests in the queue of pending connections.\n"
410 "# TYPE phpfpm_listen_queue gauge\n"
411 "phpfpm_listen_queue %d\n"
412 "# HELP phpfpm_max_listen_queue The maximum number of requests in the queue of pending connections since FPM has started.\n"
413 "# TYPE phpfpm_max_listen_queue counter\n"
414 "phpfpm_max_listen_queue %d\n"
415 "# TYPE phpfpm_listen_queue_length gauge\n"
416 "# HELP phpfpm_listen_queue_length The size of the socket queue of pending connections.\n"
417 "phpfpm_listen_queue_length %u\n"
418 "# HELP phpfpm_idle_processes The number of idle processes.\n"
419 "# TYPE phpfpm_idle_processes gauge\n"
420 "phpfpm_idle_processes %d\n"
421 "# HELP phpfpm_active_processes The number of active processes.\n"
422 "# TYPE phpfpm_active_processes gauge\n"
423 "phpfpm_active_processes %d\n"
424 "# HELP phpfpm_total_processes The number of idle + active processes.\n"
425 "# TYPE phpfpm_total_processes gauge\n"
426 "phpfpm_total_processes %d\n"
427 "# HELP phpfpm_max_active_processes The maximum number of active processes since FPM has started.\n"
428 "# TYPE phpfpm_max_active_processes counter\n"
429 "phpfpm_max_active_processes %d\n"
430 "# HELP phpfpm_max_children_reached The number of times, the process limit has been reached, when pm tries to start more children (works only for pm 'dynamic' and 'ondemand').\n"
431 "# TYPE phpfpm_max_children_reached counter\n"
432 "phpfpm_max_children_reached %u\n"
433 "# HELP phpfpm_slow_requests The number of requests that exceeded your 'request_slowlog_timeout' value.\n"
434 "# TYPE phpfpm_slow_requests counter\n"
435 "phpfpm_slow_requests %lu\n"
436 "# HELP phpfpm_memory_peak The memory usage peak since FPM has started.\n"
437 "# TYPE phpfpm_memory_peak gauge\n"
438 "phpfpm_memory_peak %zu\n"
454 time_format =
"%d/%b/%Y:%H:%M:%S %z";
458 "process manager: %s\n"
461 "accepted conn: %lu\n"
463 "max listen queue: %d\n"
464 "listen queue len: %u\n"
465 "idle processes: %d\n"
466 "active processes: %d\n"
467 "total processes: %d\n"
468 "max active processes: %d\n"
469 "max children reached: %u\n"
470 "slow requests: %lu\n"
471 "memory peak: %zu\n";
476 "************************\n"
482 "request duration: %lu\n"
483 "request method: %s\n"
484 "request URI: %s%s%s\n"
485 "content length: %zu\n"
488 "last request cpu: %.2f\n"
489 "last request memory: %zu\n";
494 if (has_start_time) {
500 (
unsigned long) (now_epoch - scoreboard_p->
start_epoch),
516 (
unsigned long) (now_epoch - scoreboard_p->
start_epoch),
544 struct timeval duration,
now;
554 for (i=0; i<scoreboard_p->
nprocs; i++) {
555 if (!scoreboard_p->procs[i].used) {
558 proc = &scoreboard_p->procs[i];
563 if (full_separator) {
564 PUTS(full_separator);
569 tmp_query_string =
NULL;
576 }
else if (encode_json) {
582 if (tmp_query_string) {
583 query_string =
ZSTR_VAL(tmp_query_string);
585 if (encode_json &&
ZSTR_LEN(tmp_query_string) >= 2) {
586 query_string[
ZSTR_LEN(tmp_query_string) - 1] =
'\0';
593 if (proc->cpu_duration.tv_sec == 0 && proc->cpu_duration.tv_usec == 0) {
596 cpu = (proc->last_request_cpu.tms_utime + proc->last_request_cpu.tms_stime + proc->last_request_cpu.tms_cutime + proc->last_request_cpu.tms_cstime) / fpm_scoreboard_get_tick() / (proc->cpu_duration.tv_sec + proc->cpu_duration.tv_usec / 1000000.) * 100.;
611 (
unsigned long) (duration.tv_sec * 1000000UL + duration.tv_usec),
614 query_string ?
"?" :
"",
615 query_string ? query_string :
"",
624 if (tmp_query_string) {
625 zend_string_free(tmp_query_string);
SAPI_API int sapi_add_header_ex(const char *header_line, size_t header_line_len, bool duplicate, bool replace)
int fpm_clock_get(struct timeval *tv)
#define timersub(tvp, uvp, vvp)
bool fpm_php_is_key_in_table(zend_string *table, const char *key, size_t key_len)
void fpm_request_executing(void)
const char * fpm_request_get_stage_name(int stage)
struct fpm_scoreboard_proc_s * fpm_scoreboard_proc_acquire(struct fpm_scoreboard_s *scoreboard, int child_index, int nohang)
void fpm_scoreboard_free_copy(struct fpm_scoreboard_s *scoreboard)
void fpm_scoreboard_release(struct fpm_scoreboard_s *scoreboard)
void fpm_scoreboard_proc_release(struct fpm_scoreboard_proc_s *proc)
struct fpm_scoreboard_s * fpm_scoreboard_get(void)
struct fpm_scoreboard_s * fpm_scoreboard_copy(struct fpm_scoreboard_s *scoreboard, int copy_procs)
struct fpm_scoreboard_s * fpm_scoreboard_acquire(struct fpm_scoreboard_s *scoreboard, int nohang)
int fpm_status_handle_request(void)
int fpm_status_export_to_zval(zval *status)
int fpm_status_init_child(struct fpm_worker_pool_s *wp)
PHPAPI zend_string * php_escape_html_entities_ex(const unsigned char *old, size_t oldlen, int all, int flags, const char *hint_charset, bool double_encode, bool quiet)
PHP_JSON_API zend_string * php_json_encode_string(const char *s, size_t len, int options)
strftime(string $format, ?int $timestamp=null)
localtime(?int $timestamp=null, bool $associative=false)
#define PHP_JSON_INVALID_UTF8_IGNORE
#define ENT_HTML_IGNORE_ERRORS
char script_filename[256]
enum fpm_request_stage_e request_stage
unsigned int max_children_reached
struct fpm_scoreboard_s * shared
unsigned long int slow_rq
unsigned long int requests
struct fpm_worker_pool_config_s * config
#define safe_emalloc(nmemb, size, offset)
strcmp(string $string1, string $string2)
zend_string_release_ex(func->internal_function.function_name, 0)
struct _zend_string zend_string
#define ZSTR_INIT_LITERAL(s, persistent)