mirror of
https://github.com/php/php-src.git
synced 2024-09-22 10:27:25 +00:00
- Implemented FR #54577 (Enhanced status page with full status and details about each processes
- Added a web page (status.html) for real-time FPM status - Fixed missing Expires and Cache-Control headers for ping and status pages
This commit is contained in:
parent
5f75a28d01
commit
217382d4ef
7
NEWS
7
NEWS
@ -18,6 +18,13 @@ PHP NEWS
|
|||||||
- PDO ODBC driver:
|
- PDO ODBC driver:
|
||||||
. Fixed data type usage in 64bit. (leocsilva at gmail dot com)
|
. Fixed data type usage in 64bit. (leocsilva at gmail dot com)
|
||||||
|
|
||||||
|
- PHP-FPM SAPI:
|
||||||
|
. Implemented FR #54577 (Enhanced status page with full status and details
|
||||||
|
about each processes. Also provide a web page (status.html) for
|
||||||
|
real-time FPM status. (fat)
|
||||||
|
. Fixed missing Expires and Cache-Control headers for ping and status pages.
|
||||||
|
(fat)
|
||||||
|
|
||||||
- SPL extension:
|
- SPL extension:
|
||||||
. Fixed bug #54971 (Wrong result when using iterator_to_array with use_keys
|
. Fixed bug #54971 (Wrong result when using iterator_to_array with use_keys
|
||||||
on true). (Pierrick)
|
on true). (Pierrick)
|
||||||
|
@ -26,3 +26,6 @@ install-fpm: install-sapi
|
|||||||
@$(mkinstalldirs) $(INSTALL_ROOT)$(mandir)/man8
|
@$(mkinstalldirs) $(INSTALL_ROOT)$(mandir)/man8
|
||||||
@$(INSTALL_DATA) sapi/fpm/php-fpm.8 $(INSTALL_ROOT)$(mandir)/man8/php-fpm$(program_suffix).8
|
@$(INSTALL_DATA) sapi/fpm/php-fpm.8 $(INSTALL_ROOT)$(mandir)/man8/php-fpm$(program_suffix).8
|
||||||
|
|
||||||
|
@echo "Installing PHP FPM status page: $(INSTALL_ROOT)$(datadir)/fpm/"
|
||||||
|
@$(mkinstalldirs) $(INSTALL_ROOT)$(datadir)/fpm
|
||||||
|
@$(INSTALL_DATA) sapi/fpm/status.html $(INSTALL_ROOT)$(datadir)/fpm/status.html
|
||||||
|
@ -49,7 +49,6 @@ int fpm_init(int argc, char **argv, char *config, char *prefix, int test_conf) /
|
|||||||
|
|
||||||
if (0 > fpm_php_init_main() ||
|
if (0 > fpm_php_init_main() ||
|
||||||
0 > fpm_stdio_init_main() ||
|
0 > fpm_stdio_init_main() ||
|
||||||
0 > fpm_log_init_main() ||
|
|
||||||
0 > fpm_conf_init_main(test_conf) ||
|
0 > fpm_conf_init_main(test_conf) ||
|
||||||
0 > fpm_unix_init_main() ||
|
0 > fpm_unix_init_main() ||
|
||||||
0 > fpm_scoreboard_init_main() ||
|
0 > fpm_scoreboard_init_main() ||
|
||||||
|
@ -344,7 +344,8 @@ static void fpm_child_resources_use(struct fpm_child_s *child) /* {{{ */
|
|||||||
}
|
}
|
||||||
fpm_scoreboard_free(wp->scoreboard);
|
fpm_scoreboard_free(wp->scoreboard);
|
||||||
}
|
}
|
||||||
fpm_scoreboard_child_use(child->wp->scoreboard, child->scoreboard_i, child->pid);
|
|
||||||
|
fpm_scoreboard_child_use(child->wp->scoreboard, child->scoreboard_i, getpid());
|
||||||
fpm_stdio_child_use_pipes(child);
|
fpm_stdio_child_use_pipes(child);
|
||||||
fpm_child_free(child);
|
fpm_child_free(child);
|
||||||
}
|
}
|
||||||
|
@ -29,9 +29,6 @@
|
|||||||
|
|
||||||
static char *fpm_log_format = NULL;
|
static char *fpm_log_format = NULL;
|
||||||
static int fpm_log_fd = -1;
|
static int fpm_log_fd = -1;
|
||||||
#ifdef HAVE_TIMES
|
|
||||||
static float tick;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int fpm_log_open(int reopen) /* {{{ */
|
int fpm_log_open(int reopen) /* {{{ */
|
||||||
{
|
{
|
||||||
@ -67,24 +64,6 @@ int fpm_log_open(int reopen) /* {{{ */
|
|||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
int fpm_log_init_main() /* {{{ */
|
|
||||||
{
|
|
||||||
#ifdef HAVE_TIMES
|
|
||||||
#if (defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK))
|
|
||||||
tick = sysconf(_SC_CLK_TCK);
|
|
||||||
#else /* _SC_CLK_TCK */
|
|
||||||
#ifdef HZ
|
|
||||||
tick = HZ;
|
|
||||||
#else /* HZ */
|
|
||||||
tick = 100;
|
|
||||||
#endif /* HZ */
|
|
||||||
#endif /* _SC_CLK_TCK */
|
|
||||||
zlog(ZLOG_DEBUG, "got clock tick '%.0f'", tick);
|
|
||||||
#endif /* HAVE_TIMES */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* }}} */
|
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
int fpm_log_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
|
int fpm_log_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
|
||||||
{
|
{
|
||||||
@ -122,7 +101,6 @@ int fpm_log_write(char *log_format TSRMLS_DC) /* {{{ */
|
|||||||
size_t len, len2;
|
size_t len, len2;
|
||||||
struct fpm_scoreboard_proc_s proc, *proc_p;
|
struct fpm_scoreboard_proc_s proc, *proc_p;
|
||||||
struct fpm_scoreboard_s *scoreboard;
|
struct fpm_scoreboard_s *scoreboard;
|
||||||
struct timeval uptime, now;
|
|
||||||
char tmp[129];
|
char tmp[129];
|
||||||
char format[129];
|
char format[129];
|
||||||
time_t now_epoch;
|
time_t now_epoch;
|
||||||
@ -141,7 +119,6 @@ int fpm_log_write(char *log_format TSRMLS_DC) /* {{{ */
|
|||||||
test = 1;
|
test = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fpm_clock_get(&now);
|
|
||||||
now_epoch = time(NULL);
|
now_epoch = time(NULL);
|
||||||
|
|
||||||
if (!test) {
|
if (!test) {
|
||||||
@ -157,8 +134,6 @@ int fpm_log_write(char *log_format TSRMLS_DC) /* {{{ */
|
|||||||
}
|
}
|
||||||
proc = *proc_p;
|
proc = *proc_p;
|
||||||
fpm_scoreboard_proc_release(proc_p);
|
fpm_scoreboard_proc_release(proc_p);
|
||||||
|
|
||||||
timersub(&now, &proc.accepted, &uptime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
token = 0;
|
token = 0;
|
||||||
@ -198,19 +173,15 @@ int fpm_log_write(char *log_format TSRMLS_DC) /* {{{ */
|
|||||||
case 'C': /* %CPU */
|
case 'C': /* %CPU */
|
||||||
if (format[0] == '\0' || !strcasecmp(format, "total")) {
|
if (format[0] == '\0' || !strcasecmp(format, "total")) {
|
||||||
if (!test) {
|
if (!test) {
|
||||||
tms_total =
|
tms_total = proc.last_request_cpu.tms_utime + proc.last_request_cpu.tms_stime + proc.last_request_cpu.tms_cutime + proc.last_request_cpu.tms_cstime;
|
||||||
(proc.cpu_finished.tms_utime + proc.cpu_finished.tms_stime + proc.cpu_finished.tms_cutime + proc.cpu_finished.tms_cstime)
|
|
||||||
-
|
|
||||||
(proc.cpu_accepted.tms_utime + proc.cpu_accepted.tms_stime + proc.cpu_accepted.tms_cutime + proc.cpu_accepted.tms_cstime)
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
} else if (!strcasecmp(format, "user")) {
|
} else if (!strcasecmp(format, "user")) {
|
||||||
if (!test) {
|
if (!test) {
|
||||||
tms_total = (proc.cpu_finished.tms_utime + proc.cpu_finished.tms_cutime) - (proc.cpu_accepted.tms_utime + proc.cpu_accepted.tms_cutime);
|
tms_total = proc.last_request_cpu.tms_utime + proc.last_request_cpu.tms_cutime;
|
||||||
}
|
}
|
||||||
} else if (!strcasecmp(format, "system")) {
|
} else if (!strcasecmp(format, "system")) {
|
||||||
if (!test) {
|
if (!test) {
|
||||||
tms_total = (proc.cpu_finished.tms_stime + proc.cpu_finished.tms_cstime) - (proc.cpu_accepted.tms_stime + proc.cpu_accepted.tms_cstime);
|
tms_total = proc.last_request_cpu.tms_stime + proc.last_request_cpu.tms_cstime;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
zlog(ZLOG_WARNING, "only 'total', 'user' or 'system' are allowed as a modifier for %%%c ('%s')", *s, format);
|
zlog(ZLOG_WARNING, "only 'total', 'user' or 'system' are allowed as a modifier for %%%c ('%s')", *s, format);
|
||||||
@ -219,7 +190,7 @@ int fpm_log_write(char *log_format TSRMLS_DC) /* {{{ */
|
|||||||
|
|
||||||
format[0] = '\0';
|
format[0] = '\0';
|
||||||
if (!test) {
|
if (!test) {
|
||||||
len2 = snprintf(b, FPM_LOG_BUFFER - len, "%.2f", tms_total / tick / (proc.cpu_duration.tv_sec + proc.cpu_duration.tv_usec / 1000000.) * 100.);
|
len2 = snprintf(b, FPM_LOG_BUFFER - len, "%.2f", tms_total / fpm_scoreboard_get_tick() / (proc.cpu_duration.tv_sec + proc.cpu_duration.tv_usec / 1000000.) * 100.);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
@ -228,19 +199,19 @@ int fpm_log_write(char *log_format TSRMLS_DC) /* {{{ */
|
|||||||
/* seconds */
|
/* seconds */
|
||||||
if (format[0] == '\0' || !strcasecmp(format, "seconds")) {
|
if (format[0] == '\0' || !strcasecmp(format, "seconds")) {
|
||||||
if (!test) {
|
if (!test) {
|
||||||
len2 = snprintf(b, FPM_LOG_BUFFER - len, "%.3f", uptime.tv_sec + uptime.tv_usec / 1000000.);
|
len2 = snprintf(b, FPM_LOG_BUFFER - len, "%.3f", proc.duration.tv_sec + proc.duration.tv_usec / 1000000.);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* miliseconds */
|
/* miliseconds */
|
||||||
} else if (!strcasecmp(format, "miliseconds") || !strcasecmp(format, "mili")) {
|
} else if (!strcasecmp(format, "miliseconds") || !strcasecmp(format, "mili")) {
|
||||||
if (!test) {
|
if (!test) {
|
||||||
len2 = snprintf(b, FPM_LOG_BUFFER - len, "%.3f", uptime.tv_sec * 1000. + uptime.tv_usec / 1000.);
|
len2 = snprintf(b, FPM_LOG_BUFFER - len, "%.3f", proc.duration.tv_sec * 1000. + proc.duration.tv_usec / 1000.);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* microseconds */
|
/* microseconds */
|
||||||
} else if (!strcasecmp(format, "microseconds") || !strcasecmp(format, "micro")) {
|
} else if (!strcasecmp(format, "microseconds") || !strcasecmp(format, "micro")) {
|
||||||
if (!test) {
|
if (!test) {
|
||||||
len2 = snprintf(b, FPM_LOG_BUFFER - len, "%lu", uptime.tv_sec * 1000000UL + uptime.tv_usec);
|
len2 = snprintf(b, FPM_LOG_BUFFER - len, "%lu", proc.duration.tv_sec * 1000000UL + proc.duration.tv_usec);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
#define FPM_LOG_H 1
|
#define FPM_LOG_H 1
|
||||||
#include "fpm_worker_pool.h"
|
#include "fpm_worker_pool.h"
|
||||||
|
|
||||||
int fpm_log_init_main();
|
|
||||||
int fpm_log_init_child(struct fpm_worker_pool_s *wp);
|
int fpm_log_init_child(struct fpm_worker_pool_s *wp);
|
||||||
int fpm_log_write(char *log_format TSRMLS_DC);
|
int fpm_log_write(char *log_format TSRMLS_DC);
|
||||||
int fpm_log_open(int reopen);
|
int fpm_log_open(int reopen);
|
||||||
|
@ -23,6 +23,19 @@
|
|||||||
|
|
||||||
#include "zlog.h"
|
#include "zlog.h"
|
||||||
|
|
||||||
|
static const char *requests_stages[] = {
|
||||||
|
[FPM_REQUEST_ACCEPTING] = "Idle",
|
||||||
|
[FPM_REQUEST_READING_HEADERS] = "Reading headers",
|
||||||
|
[FPM_REQUEST_INFO] = "Getting request informations",
|
||||||
|
[FPM_REQUEST_EXECUTING] = "Running",
|
||||||
|
[FPM_REQUEST_END] = "Ending",
|
||||||
|
[FPM_REQUEST_FINISHED] = "Finishing",
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *fpm_request_get_stage_name(int stage) {
|
||||||
|
return requests_stages[stage];
|
||||||
|
}
|
||||||
|
|
||||||
void fpm_request_accepting() /* {{{ */
|
void fpm_request_accepting() /* {{{ */
|
||||||
{
|
{
|
||||||
struct fpm_scoreboard_proc_s *proc;
|
struct fpm_scoreboard_proc_s *proc;
|
||||||
@ -38,10 +51,6 @@ void fpm_request_accepting() /* {{{ */
|
|||||||
|
|
||||||
proc->request_stage = FPM_REQUEST_ACCEPTING;
|
proc->request_stage = FPM_REQUEST_ACCEPTING;
|
||||||
proc->tv = now;
|
proc->tv = now;
|
||||||
proc->request_uri[0] = '\0';
|
|
||||||
proc->request_method[0] = '\0';
|
|
||||||
proc->script_filename[0] = '\0';
|
|
||||||
proc->content_length = 0;
|
|
||||||
fpm_scoreboard_proc_release(proc);
|
fpm_scoreboard_proc_release(proc);
|
||||||
|
|
||||||
/* idle++, active-- */
|
/* idle++, active-- */
|
||||||
@ -78,6 +87,12 @@ void fpm_request_reading_headers() /* {{{ */
|
|||||||
#ifdef HAVE_TIMES
|
#ifdef HAVE_TIMES
|
||||||
proc->cpu_accepted = cpu;
|
proc->cpu_accepted = cpu;
|
||||||
#endif
|
#endif
|
||||||
|
proc->requests++;
|
||||||
|
proc->request_uri[0] = '\0';
|
||||||
|
proc->request_method[0] = '\0';
|
||||||
|
proc->script_filename[0] = '\0';
|
||||||
|
proc->query_string[0] = '\0';
|
||||||
|
proc->content_length = 0;
|
||||||
fpm_scoreboard_proc_release(proc);
|
fpm_scoreboard_proc_release(proc);
|
||||||
|
|
||||||
/* idle--, active++, request++ */
|
/* idle--, active++, request++ */
|
||||||
@ -176,9 +191,13 @@ void fpm_request_end(TSRMLS_D) /* {{{ */
|
|||||||
}
|
}
|
||||||
proc->request_stage = FPM_REQUEST_FINISHED;
|
proc->request_stage = FPM_REQUEST_FINISHED;
|
||||||
proc->tv = now;
|
proc->tv = now;
|
||||||
|
timersub(&now, &proc->accepted, &proc->duration);
|
||||||
#ifdef HAVE_TIMES
|
#ifdef HAVE_TIMES
|
||||||
proc->cpu_finished = cpu;
|
|
||||||
timersub(&proc->tv, &proc->accepted, &proc->cpu_duration);
|
timersub(&proc->tv, &proc->accepted, &proc->cpu_duration);
|
||||||
|
proc->last_request_cpu.tms_utime = cpu.tms_utime - proc->cpu_accepted.tms_utime;
|
||||||
|
proc->last_request_cpu.tms_stime = cpu.tms_stime - proc->cpu_accepted.tms_stime;
|
||||||
|
proc->last_request_cpu.tms_cutime = cpu.tms_cutime - proc->cpu_accepted.tms_cutime;
|
||||||
|
proc->last_request_cpu.tms_cstime = cpu.tms_cstime - proc->cpu_accepted.tms_cstime;
|
||||||
#endif
|
#endif
|
||||||
proc->memory = memory;
|
proc->memory = memory;
|
||||||
fpm_scoreboard_proc_release(proc);
|
fpm_scoreboard_proc_release(proc);
|
||||||
|
@ -17,6 +17,7 @@ struct timeval;
|
|||||||
|
|
||||||
void fpm_request_check_timed_out(struct fpm_child_s *child, struct timeval *tv, int terminate_timeout, int slowlog_timeout);
|
void fpm_request_check_timed_out(struct fpm_child_s *child, struct timeval *tv, int terminate_timeout, int slowlog_timeout);
|
||||||
int fpm_request_is_idle(struct fpm_child_s *child);
|
int fpm_request_is_idle(struct fpm_child_s *child);
|
||||||
|
const char *fpm_request_get_stage_name(int stage);
|
||||||
|
|
||||||
enum fpm_request_stage_e {
|
enum fpm_request_stage_e {
|
||||||
FPM_REQUEST_ACCEPTING = 1,
|
FPM_REQUEST_ACCEPTING = 1,
|
||||||
|
@ -17,12 +17,30 @@
|
|||||||
|
|
||||||
static struct fpm_scoreboard_s *fpm_scoreboard = NULL;
|
static struct fpm_scoreboard_s *fpm_scoreboard = NULL;
|
||||||
static int fpm_scoreboard_i = -1;
|
static int fpm_scoreboard_i = -1;
|
||||||
|
#ifdef HAVE_TIMES
|
||||||
|
static float fpm_scoreboard_tick;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
int fpm_scoreboard_init_main() /* {{{ */
|
int fpm_scoreboard_init_main() /* {{{ */
|
||||||
{
|
{
|
||||||
struct fpm_worker_pool_s *wp;
|
struct fpm_worker_pool_s *wp;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
#ifdef HAVE_TIMES
|
||||||
|
#if (defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK))
|
||||||
|
fpm_scoreboard_tick = sysconf(_SC_CLK_TCK);
|
||||||
|
#else /* _SC_CLK_TCK */
|
||||||
|
#ifdef HZ
|
||||||
|
fpm_scoreboard_tick = HZ;
|
||||||
|
#else /* HZ */
|
||||||
|
fpm_scoreboard_tick = 100;
|
||||||
|
#endif /* HZ */
|
||||||
|
#endif /* _SC_CLK_TCK */
|
||||||
|
zlog(ZLOG_DEBUG, "got clock tick '%.0f'", fpm_scoreboard_tick);
|
||||||
|
#endif /* HAVE_TIMES */
|
||||||
|
|
||||||
|
|
||||||
for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
|
for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
|
||||||
if (wp->config->pm_max_children < 1) {
|
if (wp->config->pm_max_children < 1) {
|
||||||
zlog(ZLOG_ERROR, "[pool %s] Unable to create scoreboard SHM because max_client is not set", wp->config->name);
|
zlog(ZLOG_ERROR, "[pool %s] Unable to create scoreboard SHM because max_client is not set", wp->config->name);
|
||||||
@ -40,7 +58,11 @@ int fpm_scoreboard_init_main() /* {{{ */
|
|||||||
}
|
}
|
||||||
wp->scoreboard->nprocs = wp->config->pm_max_children;
|
wp->scoreboard->nprocs = wp->config->pm_max_children;
|
||||||
for (i=0; i<wp->scoreboard->nprocs; i++) {
|
for (i=0; i<wp->scoreboard->nprocs; i++) {
|
||||||
wp->scoreboard->procs[i] = NULL;
|
wp->scoreboard->procs[i] = fpm_shm_alloc(sizeof(struct fpm_scoreboard_proc_s));
|
||||||
|
if (!wp->scoreboard->procs[i]) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memset(wp->scoreboard->procs[i], 0, sizeof(struct fpm_scoreboard_proc_s));
|
||||||
}
|
}
|
||||||
|
|
||||||
wp->scoreboard->pm = wp->config->pm;
|
wp->scoreboard->pm = wp->config->pm;
|
||||||
@ -229,6 +251,7 @@ void fpm_scoreboard_child_use(struct fpm_scoreboard_s *scoreboard, int child_ind
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
proc->pid = pid;
|
proc->pid = pid;
|
||||||
|
proc->start_epoch = time(NULL);
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
@ -242,9 +265,8 @@ void fpm_scoreboard_proc_free(struct fpm_scoreboard_s *scoreboard, int child_ind
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scoreboard->procs[child_index]) {
|
if (scoreboard->procs[child_index] && scoreboard->procs[child_index]->used > 0) {
|
||||||
fpm_shm_free(scoreboard->procs[child_index], sizeof(struct fpm_scoreboard_proc_s));
|
memset(scoreboard->procs[child_index], 0, sizeof(struct fpm_scoreboard_proc_s));
|
||||||
scoreboard->procs[child_index] = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set this slot as free to avoid search on next alloc */
|
/* set this slot as free to avoid search on next alloc */
|
||||||
@ -262,7 +284,7 @@ int fpm_scoreboard_proc_alloc(struct fpm_scoreboard_s *scoreboard, int *child_in
|
|||||||
|
|
||||||
/* first try the slot which is supposed to be free */
|
/* first try the slot which is supposed to be free */
|
||||||
if (scoreboard->free_proc >= 0 && scoreboard->free_proc < scoreboard->nprocs) {
|
if (scoreboard->free_proc >= 0 && scoreboard->free_proc < scoreboard->nprocs) {
|
||||||
if (!scoreboard->procs[scoreboard->free_proc]) {
|
if (scoreboard->procs[scoreboard->free_proc] && !scoreboard->procs[scoreboard->free_proc]->used) {
|
||||||
i = scoreboard->free_proc;
|
i = scoreboard->free_proc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -270,7 +292,7 @@ int fpm_scoreboard_proc_alloc(struct fpm_scoreboard_s *scoreboard, int *child_in
|
|||||||
if (i < 0) { /* the supposed free slot is not, let's search for a free slot */
|
if (i < 0) { /* the supposed free slot is not, let's search for a free slot */
|
||||||
zlog(ZLOG_DEBUG, "[pool %s] the proc->free_slot was not free. Let's search", scoreboard->pool);
|
zlog(ZLOG_DEBUG, "[pool %s] the proc->free_slot was not free. Let's search", scoreboard->pool);
|
||||||
for (i=0; i<scoreboard->nprocs; i++) {
|
for (i=0; i<scoreboard->nprocs; i++) {
|
||||||
if (!scoreboard->procs[i]) { /* found */
|
if (scoreboard->procs[i] && !scoreboard->procs[i]->used) { /* found */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -282,10 +304,7 @@ int fpm_scoreboard_proc_alloc(struct fpm_scoreboard_s *scoreboard, int *child_in
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
scoreboard->procs[i] = fpm_shm_alloc(sizeof(struct fpm_scoreboard_proc_s));
|
scoreboard->procs[i]->used = 1;
|
||||||
if (!scoreboard->procs[i]) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*child_index = i;
|
*child_index = i;
|
||||||
|
|
||||||
/* supposed next slot is free */
|
/* supposed next slot is free */
|
||||||
@ -299,3 +318,11 @@ int fpm_scoreboard_proc_alloc(struct fpm_scoreboard_s *scoreboard, int *child_in
|
|||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
#ifdef HAVE_TIMES
|
||||||
|
float fpm_scoreboard_get_tick() /* {{{ */
|
||||||
|
{
|
||||||
|
return fpm_scoreboard_tick;
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@ -22,9 +22,13 @@ struct fpm_scoreboard_proc_s {
|
|||||||
atomic_t lock;
|
atomic_t lock;
|
||||||
char dummy[16];
|
char dummy[16];
|
||||||
};
|
};
|
||||||
|
int used;
|
||||||
|
time_t start_epoch;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
unsigned long requests;
|
||||||
enum fpm_request_stage_e request_stage;
|
enum fpm_request_stage_e request_stage;
|
||||||
struct timeval accepted;
|
struct timeval accepted;
|
||||||
|
struct timeval duration;
|
||||||
time_t accepted_epoch;
|
time_t accepted_epoch;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
char request_uri[128];
|
char request_uri[128];
|
||||||
@ -35,8 +39,9 @@ struct fpm_scoreboard_proc_s {
|
|||||||
char auth_user[32];
|
char auth_user[32];
|
||||||
#ifdef HAVE_TIMES
|
#ifdef HAVE_TIMES
|
||||||
struct tms cpu_accepted;
|
struct tms cpu_accepted;
|
||||||
struct tms cpu_finished;
|
|
||||||
struct timeval cpu_duration;
|
struct timeval cpu_duration;
|
||||||
|
struct tms last_request_cpu;
|
||||||
|
struct timeval last_request_cpu_duration;
|
||||||
#endif
|
#endif
|
||||||
size_t memory;
|
size_t memory;
|
||||||
};
|
};
|
||||||
@ -81,4 +86,8 @@ void fpm_scoreboard_child_use(struct fpm_scoreboard_s *scoreboard, int child_ind
|
|||||||
void fpm_scoreboard_proc_free(struct fpm_scoreboard_s *scoreboard, int child_index);
|
void fpm_scoreboard_proc_free(struct fpm_scoreboard_s *scoreboard, int child_index);
|
||||||
int fpm_scoreboard_proc_alloc(struct fpm_scoreboard_s *scoreboard, int *child_index);
|
int fpm_scoreboard_proc_alloc(struct fpm_scoreboard_s *scoreboard, int *child_index);
|
||||||
|
|
||||||
|
#ifdef HAVE_TIMES
|
||||||
|
float fpm_scoreboard_get_tick();
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "fpm_scoreboard.h"
|
#include "fpm_scoreboard.h"
|
||||||
#include "zlog.h"
|
#include "zlog.h"
|
||||||
#include "fpm_atomic.h"
|
#include "fpm_atomic.h"
|
||||||
|
#include <ext/standard/html.h>
|
||||||
|
|
||||||
static char *fpm_status_uri = NULL;
|
static char *fpm_status_uri = NULL;
|
||||||
static char *fpm_status_ping_uri = NULL;
|
static char *fpm_status_ping_uri = NULL;
|
||||||
@ -46,9 +47,12 @@ int fpm_status_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
|
|||||||
int fpm_status_handle_request(TSRMLS_D) /* {{{ */
|
int fpm_status_handle_request(TSRMLS_D) /* {{{ */
|
||||||
{
|
{
|
||||||
struct fpm_scoreboard_s scoreboard, *scoreboard_p;
|
struct fpm_scoreboard_s scoreboard, *scoreboard_p;
|
||||||
// struct fpm_scoreboard_proc_s proc;
|
struct fpm_scoreboard_proc_s proc;
|
||||||
char *buffer, *syntax, *time_format, time_buffer[64];
|
char *buffer, *time_format, time_buffer[64];
|
||||||
time_t now_epoch;
|
time_t now_epoch;
|
||||||
|
int full, encode;
|
||||||
|
char *short_syntax, *short_post;
|
||||||
|
char *full_pre, *full_syntax, *full_post, *full_separator;
|
||||||
|
|
||||||
if (!SG(request_info).request_uri) {
|
if (!SG(request_info).request_uri) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -56,7 +60,10 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */
|
|||||||
|
|
||||||
/* PING */
|
/* PING */
|
||||||
if (fpm_status_ping_uri && fpm_status_ping_response && !strcmp(fpm_status_ping_uri, SG(request_info).request_uri)) {
|
if (fpm_status_ping_uri && fpm_status_ping_response && !strcmp(fpm_status_ping_uri, SG(request_info).request_uri)) {
|
||||||
|
fpm_request_executing();
|
||||||
sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1 TSRMLS_CC);
|
sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1 TSRMLS_CC);
|
||||||
|
sapi_add_header_ex(ZEND_STRL("Expires: Thu, 01 Jan 1970 00:00:00 GMT"), 1, 1 TSRMLS_CC);
|
||||||
|
sapi_add_header_ex(ZEND_STRL("Cache-Control: no-cache, no-store, must-revalidate, max-age=0"), 1, 1 TSRMLS_CC);
|
||||||
SG(sapi_headers).http_response_code = 200;
|
SG(sapi_headers).http_response_code = 200;
|
||||||
PUTS(fpm_status_ping_response);
|
PUTS(fpm_status_ping_response);
|
||||||
return 1;
|
return 1;
|
||||||
@ -64,12 +71,15 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */
|
|||||||
|
|
||||||
/* STATUS */
|
/* STATUS */
|
||||||
if (fpm_status_uri && !strcmp(fpm_status_uri, SG(request_info).request_uri)) {
|
if (fpm_status_uri && !strcmp(fpm_status_uri, SG(request_info).request_uri)) {
|
||||||
|
fpm_request_executing();
|
||||||
|
|
||||||
scoreboard_p = fpm_scoreboard_get();
|
scoreboard_p = fpm_scoreboard_get();
|
||||||
if (!scoreboard_p) {
|
if (!scoreboard_p) {
|
||||||
zlog(ZLOG_ERROR, "status: unable to find or access status shared memory");
|
zlog(ZLOG_ERROR, "status: unable to find or access status shared memory");
|
||||||
SG(sapi_headers).http_response_code = 500;
|
SG(sapi_headers).http_response_code = 500;
|
||||||
sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1 TSRMLS_CC);
|
sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1 TSRMLS_CC);
|
||||||
|
sapi_add_header_ex(ZEND_STRL("Expires: Thu, 01 Jan 1970 00:00:00 GMT"), 1, 1 TSRMLS_CC);
|
||||||
|
sapi_add_header_ex(ZEND_STRL("Cache-Control: no-cache, no-store, must-revalidate, max-age=0"), 1, 1 TSRMLS_CC);
|
||||||
PUTS("Internal error. Please review log file for errors.");
|
PUTS("Internal error. Please review log file for errors.");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -78,6 +88,8 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */
|
|||||||
zlog(ZLOG_NOTICE, "[pool %s] status: scoreboard already in used.", scoreboard_p->pool);
|
zlog(ZLOG_NOTICE, "[pool %s] status: scoreboard already in used.", scoreboard_p->pool);
|
||||||
SG(sapi_headers).http_response_code = 503;
|
SG(sapi_headers).http_response_code = 503;
|
||||||
sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1 TSRMLS_CC);
|
sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1 TSRMLS_CC);
|
||||||
|
sapi_add_header_ex(ZEND_STRL("Expires: Thu, 01 Jan 1970 00:00:00 GMT"), 1, 1 TSRMLS_CC);
|
||||||
|
sapi_add_header_ex(ZEND_STRL("Cache-Control: no-cache, no-store, must-revalidate, max-age=0"), 1, 1 TSRMLS_CC);
|
||||||
PUTS("Server busy. Please try again later.");
|
PUTS("Server busy. Please try again later.");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -89,38 +101,99 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */
|
|||||||
zlog(ZLOG_ERROR, "[pool %s] invalid status values", scoreboard.pool);
|
zlog(ZLOG_ERROR, "[pool %s] invalid status values", scoreboard.pool);
|
||||||
SG(sapi_headers).http_response_code = 500;
|
SG(sapi_headers).http_response_code = 500;
|
||||||
sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1 TSRMLS_CC);
|
sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1 TSRMLS_CC);
|
||||||
|
sapi_add_header_ex(ZEND_STRL("Expires: Thu, 01 Jan 1970 00:00:00 GMT"), 1, 1 TSRMLS_CC);
|
||||||
|
sapi_add_header_ex(ZEND_STRL("Cache-Control: no-cache, no-store, must-revalidate, max-age=0"), 1, 1 TSRMLS_CC);
|
||||||
PUTS("Internal error. Please review log file for errors.");
|
PUTS("Internal error. Please review log file for errors.");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* full status ? */
|
||||||
|
full = SG(request_info).request_uri && strstr(SG(request_info).query_string, "full");
|
||||||
|
short_syntax = short_post = NULL;
|
||||||
|
full_separator = full_pre = full_syntax = full_post = NULL;
|
||||||
|
encode = 0;
|
||||||
|
|
||||||
/* HTML */
|
/* HTML */
|
||||||
if (SG(request_info).query_string && strstr(SG(request_info).query_string, "html")) {
|
if (SG(request_info).query_string && strstr(SG(request_info).query_string, "html")) {
|
||||||
sapi_add_header_ex(ZEND_STRL("Content-Type: text/html"), 1, 1 TSRMLS_CC);
|
sapi_add_header_ex(ZEND_STRL("Content-Type: text/html"), 1, 1 TSRMLS_CC);
|
||||||
time_format = "%d/%b/%Y:%H:%M:%S %z";
|
time_format = "%d/%b/%Y:%H:%M:%S %z";
|
||||||
syntax =
|
encode = 1;
|
||||||
|
|
||||||
|
short_syntax =
|
||||||
|
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"
|
||||||
|
"<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
|
||||||
|
"<head><title>PHP-FPM Status Page</title></head>\n"
|
||||||
|
"<body>\n"
|
||||||
"<table>\n"
|
"<table>\n"
|
||||||
"<tr><th>pool</th><td>%s</td></tr>\n"
|
"<tr><th>pool</th><td>%s</td></tr>\n"
|
||||||
"<tr><th>process manager</th><td>%s</td></tr>\n"
|
"<tr><th>process manager</th><td>%s</td></tr>\n"
|
||||||
"<tr><th>start time</th><td>%s</td></tr>\n"
|
"<tr><th>start time</th><td>%s</td></tr>\n"
|
||||||
"<tr><th>start since</th><td>%lu</td></tr>\n"
|
"<tr><th>start since</th><td>%lu</td></tr>\n"
|
||||||
"<tr><th>accepted conn</th><td>%lu</td></tr>\n"
|
"<tr><th>accepted conn</th><td>%lu</td></tr>\n"
|
||||||
#if HAVE_FPM_LQ
|
#if HAVE_FPM_LQ
|
||||||
"<tr><th>listen queue</th><td>%u</td></tr>\n"
|
"<tr><th>listen queue</th><td>%u</td></tr>\n"
|
||||||
"<tr><th>max listen queue</th><td>%u</td></tr>\n"
|
"<tr><th>max listen queue</th><td>%u</td></tr>\n"
|
||||||
"<tr><th>listen queue len</th><td>%d</td></tr>\n"
|
"<tr><th>listen queue len</th><td>%d</td></tr>\n"
|
||||||
#endif
|
#endif
|
||||||
"<tr><th>idle processes</th><td>%d</td></tr>\n"
|
"<tr><th>idle processes</th><td>%d</td></tr>\n"
|
||||||
"<tr><th>active processes</th><td>%d</td></tr>\n"
|
"<tr><th>active processes</th><td>%d</td></tr>\n"
|
||||||
"<tr><th>total processes</th><td>%d</td></tr>\n"
|
"<tr><th>total processes</th><td>%d</td></tr>\n"
|
||||||
"<tr><th>max active processes</th><td>%d</td></tr>\n"
|
"<tr><th>max active processes</th><td>%d</td></tr>\n"
|
||||||
"<tr><th>max children reached</th><td>%u</td></tr>\n"
|
"<tr><th>max children reached</th><td>%u</td></tr>\n"
|
||||||
"</table>";
|
"</table>\n";
|
||||||
|
|
||||||
|
if (!full) {
|
||||||
|
short_post = "</body></html>";
|
||||||
|
} else {
|
||||||
|
full_pre =
|
||||||
|
"<table border=\"1\">\n"
|
||||||
|
"<tr>"
|
||||||
|
"<th>pid</th>"
|
||||||
|
"<th>state</th>"
|
||||||
|
"<th>start time</th>"
|
||||||
|
"<th>start since</th>"
|
||||||
|
"<th>requests</th>"
|
||||||
|
"<th>request duration</th>"
|
||||||
|
"<th>request method</th>"
|
||||||
|
"<th>request uri</th>"
|
||||||
|
"<th>content length</th>"
|
||||||
|
"<th>user</th>"
|
||||||
|
"<th>script</th>"
|
||||||
|
#if HAVE_FPM_LQ
|
||||||
|
"<th>last request cpu</th>"
|
||||||
|
#endif
|
||||||
|
"<th>last request memory</th>"
|
||||||
|
"</tr>\n";
|
||||||
|
|
||||||
|
full_syntax =
|
||||||
|
"<tr>"
|
||||||
|
"<td>%d</td>"
|
||||||
|
"<td>%s</td>"
|
||||||
|
"<td>%s</td>"
|
||||||
|
"<td>%lu</td>"
|
||||||
|
"<td>%lu</td>"
|
||||||
|
"<td>%lu</td>"
|
||||||
|
"<td>%s</td>"
|
||||||
|
"<td>%s%s%s</td>"
|
||||||
|
"<td>%zu</td>"
|
||||||
|
"<td>%s</td>"
|
||||||
|
"<td>%s</td>"
|
||||||
|
#if HAVE_FPM_LQ
|
||||||
|
"<td>%.2f</td>"
|
||||||
|
#endif
|
||||||
|
"<td>%zu</td>"
|
||||||
|
"</tr>\n";
|
||||||
|
|
||||||
|
full_post = "</table></body></html>";
|
||||||
|
}
|
||||||
|
|
||||||
/* XML */
|
/* XML */
|
||||||
} else if (SG(request_info).request_uri && strstr(SG(request_info).query_string, "xml")) {
|
} else if (SG(request_info).request_uri && strstr(SG(request_info).query_string, "xml")) {
|
||||||
sapi_add_header_ex(ZEND_STRL("Content-Type: text/xml"), 1, 1 TSRMLS_CC);
|
sapi_add_header_ex(ZEND_STRL("Content-Type: text/xml"), 1, 1 TSRMLS_CC);
|
||||||
time_format = "%s";
|
time_format = "%s";
|
||||||
syntax =
|
encode = 1;
|
||||||
|
|
||||||
|
short_syntax =
|
||||||
"<?xml version=\"1.0\" ?>\n"
|
"<?xml version=\"1.0\" ?>\n"
|
||||||
"<status>\n"
|
"<status>\n"
|
||||||
"<pool>%s</pool>\n"
|
"<pool>%s</pool>\n"
|
||||||
@ -137,14 +210,40 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */
|
|||||||
"<active-processes>%d</active-processes>\n"
|
"<active-processes>%d</active-processes>\n"
|
||||||
"<total-processes>%d</total-processes>\n"
|
"<total-processes>%d</total-processes>\n"
|
||||||
"<max-active-processes>%d</max-active-processes>\n"
|
"<max-active-processes>%d</max-active-processes>\n"
|
||||||
"<max-children-reached>%u</max-children-reached>\n"
|
"<max-children-reached>%u</max-children-reached>\n";
|
||||||
"</status>";
|
|
||||||
|
if (!full) {
|
||||||
|
short_post = "</status>";
|
||||||
|
} else {
|
||||||
|
full_pre = "<processes>\n";
|
||||||
|
full_syntax =
|
||||||
|
"<process>"
|
||||||
|
"<pid>%d</pid>"
|
||||||
|
"<state>%s</state>"
|
||||||
|
"<start-time>%s</start-time>"
|
||||||
|
"<start-since>%lu</start-since>"
|
||||||
|
"<requests>%lu</requests>"
|
||||||
|
"<request-duration>%lu</request-duration>"
|
||||||
|
"<request-method>%s</request-method>"
|
||||||
|
"<request-uri>%s%s%s</request-uri>"
|
||||||
|
"<content-length>%zu</content-length>"
|
||||||
|
"<user>%s</user>"
|
||||||
|
"<script>%s</script>"
|
||||||
|
#if HAVE_FPM_LQ
|
||||||
|
"<last-request-cpu>%.2f</last-request-cpu>"
|
||||||
|
#endif
|
||||||
|
"<last-request-memory>%zu</last-request-memory>"
|
||||||
|
"</process>\n"
|
||||||
|
;
|
||||||
|
full_post = "</processes>\n</status>";
|
||||||
|
}
|
||||||
|
|
||||||
/* JSON */
|
/* JSON */
|
||||||
} else if (SG(request_info).request_uri && strstr(SG(request_info).query_string, "json")) {
|
} else if (SG(request_info).request_uri && strstr(SG(request_info).query_string, "json")) {
|
||||||
sapi_add_header_ex(ZEND_STRL("Content-Type: application/json"), 1, 1 TSRMLS_CC);
|
sapi_add_header_ex(ZEND_STRL("Content-Type: application/json"), 1, 1 TSRMLS_CC);
|
||||||
time_format = "%s";
|
time_format = "%s";
|
||||||
syntax =
|
|
||||||
|
short_syntax =
|
||||||
"{"
|
"{"
|
||||||
"\"pool\":\"%s\","
|
"\"pool\":\"%s\","
|
||||||
"\"process manager\":\"%s\","
|
"\"process manager\":\"%s\","
|
||||||
@ -160,14 +259,41 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */
|
|||||||
"\"active processes\":%d,"
|
"\"active processes\":%d,"
|
||||||
"\"total processes\":%d,"
|
"\"total processes\":%d,"
|
||||||
"\"max active processes\":%d,"
|
"\"max active processes\":%d,"
|
||||||
"\"max children reached\":%u"
|
"\"max children reached\":%u";
|
||||||
"}";
|
|
||||||
|
if (!full) {
|
||||||
|
short_post = "}";
|
||||||
|
} else {
|
||||||
|
full_separator = ",";
|
||||||
|
full_pre = ", \"processes\":[";
|
||||||
|
|
||||||
|
full_syntax = "{"
|
||||||
|
"\"pid\":%d,"
|
||||||
|
"\"state\":\"%s\","
|
||||||
|
"\"start time\":%s,"
|
||||||
|
"\"start since\":%lu,"
|
||||||
|
"\"requests\":%lu,"
|
||||||
|
"\"request duration\":%lu,"
|
||||||
|
"\"request method\":\"%s\","
|
||||||
|
"\"request uri\":\"%s%s%s\","
|
||||||
|
"\"content length\":%zu,"
|
||||||
|
"\"user\":\"%s\","
|
||||||
|
"\"script\":\"%s\","
|
||||||
|
#if HAVE_FPM_LQ
|
||||||
|
"\"last request cpu\":%.2f,"
|
||||||
|
#endif
|
||||||
|
"\"last request memory\":%zu"
|
||||||
|
"}";
|
||||||
|
|
||||||
|
full_post = "]}";
|
||||||
|
}
|
||||||
|
|
||||||
/* TEXT */
|
/* TEXT */
|
||||||
} else {
|
} else {
|
||||||
sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1 TSRMLS_CC);
|
sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1 TSRMLS_CC);
|
||||||
time_format = "%d/%b/%Y:%H:%M:%S %z";
|
time_format = "%d/%b/%Y:%H:%M:%S %z";
|
||||||
syntax =
|
|
||||||
|
short_syntax =
|
||||||
"pool: %s\n"
|
"pool: %s\n"
|
||||||
"process manager: %s\n"
|
"process manager: %s\n"
|
||||||
"start time: %s\n"
|
"start time: %s\n"
|
||||||
@ -183,11 +309,35 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */
|
|||||||
"total processes: %d\n"
|
"total processes: %d\n"
|
||||||
"max active processes: %d\n"
|
"max active processes: %d\n"
|
||||||
"max children reached: %u\n";
|
"max children reached: %u\n";
|
||||||
|
|
||||||
|
if (full) {
|
||||||
|
full_syntax =
|
||||||
|
"\n"
|
||||||
|
"************************\n"
|
||||||
|
"pid: %d\n"
|
||||||
|
"state: %s\n"
|
||||||
|
"start time: %s\n"
|
||||||
|
"start since: %lu\n"
|
||||||
|
"requests: %lu\n"
|
||||||
|
"request duration: %lu\n"
|
||||||
|
"request method: %s\n"
|
||||||
|
"request URI: %s%s%s\n"
|
||||||
|
"content length: %zu\n"
|
||||||
|
"user: %s\n"
|
||||||
|
"script: %s\n"
|
||||||
|
#ifdef HAVE_FPM_LQ
|
||||||
|
"last request cpu: %.2f\n"
|
||||||
|
#endif
|
||||||
|
"last request memory: %zu\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sapi_add_header_ex(ZEND_STRL("Expires: Thu, 01 Jan 1970 00:00:00 GMT"), 1, 1 TSRMLS_CC);
|
||||||
|
sapi_add_header_ex(ZEND_STRL("Cache-Control: no-cache, no-store, must-revalidate, max-age=0"), 1, 1 TSRMLS_CC);
|
||||||
|
|
||||||
strftime(time_buffer, sizeof(time_buffer) - 1, time_format, localtime(&scoreboard.start_epoch));
|
strftime(time_buffer, sizeof(time_buffer) - 1, time_format, localtime(&scoreboard.start_epoch));
|
||||||
now_epoch = time(NULL);
|
now_epoch = time(NULL);
|
||||||
spprintf(&buffer, 0, syntax,
|
spprintf(&buffer, 0, short_syntax,
|
||||||
scoreboard.pool,
|
scoreboard.pool,
|
||||||
scoreboard.pm == PM_STYLE_STATIC ? "static" : "dynamic",
|
scoreboard.pm == PM_STYLE_STATIC ? "static" : "dynamic",
|
||||||
time_buffer,
|
time_buffer,
|
||||||
@ -208,6 +358,96 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */
|
|||||||
PUTS(buffer);
|
PUTS(buffer);
|
||||||
efree(buffer);
|
efree(buffer);
|
||||||
|
|
||||||
|
if (short_post) {
|
||||||
|
PUTS(short_post);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* no need to test the var 'full' */
|
||||||
|
if (full_syntax) {
|
||||||
|
int i, len, first;
|
||||||
|
char *query_string;
|
||||||
|
struct timeval duration, now;
|
||||||
|
#ifdef HAVE_FPM_LQ
|
||||||
|
float cpu;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fpm_clock_get(&now);
|
||||||
|
|
||||||
|
if (full_pre) {
|
||||||
|
PUTS(full_pre);
|
||||||
|
}
|
||||||
|
|
||||||
|
first = 1;
|
||||||
|
for (i=0; i<scoreboard_p->nprocs; i++) {
|
||||||
|
if (!scoreboard_p->procs[i] || !scoreboard_p->procs[i]->used) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
proc = *scoreboard_p->procs[i];
|
||||||
|
|
||||||
|
if (first) {
|
||||||
|
first = 0;
|
||||||
|
} else {
|
||||||
|
if (full_separator) {
|
||||||
|
PUTS(full_separator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
query_string = NULL;
|
||||||
|
len = 0;
|
||||||
|
if (proc.query_string[0] != '\0') {
|
||||||
|
if (!encode) {
|
||||||
|
query_string = proc.query_string;
|
||||||
|
} else {
|
||||||
|
query_string = php_escape_html_entities_ex((unsigned char *)proc.query_string, strlen(proc.query_string), &len, 1, ENT_HTML_IGNORE_ERRORS & ENT_COMPAT, NULL, 1 TSRMLS_CC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_FPM_LQ
|
||||||
|
/* prevent NaN */
|
||||||
|
if (proc.cpu_duration.tv_sec == 0 && proc.cpu_duration.tv_usec == 0) {
|
||||||
|
cpu = 0.;
|
||||||
|
} else {
|
||||||
|
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.;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (proc.request_stage == FPM_REQUEST_ACCEPTING) {
|
||||||
|
duration = proc.duration;
|
||||||
|
} else {
|
||||||
|
timersub(&now, &proc.accepted, &duration);
|
||||||
|
}
|
||||||
|
strftime(time_buffer, sizeof(time_buffer) - 1, time_format, localtime(&proc.start_epoch));
|
||||||
|
spprintf(&buffer, 0, full_syntax,
|
||||||
|
proc.pid,
|
||||||
|
fpm_request_get_stage_name(proc.request_stage),
|
||||||
|
time_buffer,
|
||||||
|
now_epoch - proc.start_epoch,
|
||||||
|
proc.requests,
|
||||||
|
duration.tv_sec * 1000000UL + duration.tv_usec,
|
||||||
|
proc.request_method[0] != '\0' ? proc.request_method : "-",
|
||||||
|
proc.request_uri[0] != '\0' ? proc.request_uri : "-",
|
||||||
|
query_string ? "?" : "",
|
||||||
|
query_string ? query_string : "",
|
||||||
|
proc.content_length,
|
||||||
|
proc.auth_user[0] != '\0' ? proc.auth_user : "-",
|
||||||
|
proc.script_filename[0] != '\0' ? proc.script_filename : "-",
|
||||||
|
#ifdef HAVE_FPM_LQ
|
||||||
|
proc.request_stage == FPM_REQUEST_ACCEPTING ? cpu : 0.,
|
||||||
|
#endif
|
||||||
|
proc.request_stage == FPM_REQUEST_ACCEPTING ? proc.memory : 0);
|
||||||
|
PUTS(buffer);
|
||||||
|
efree(buffer);
|
||||||
|
|
||||||
|
if (len > 0 && query_string) {
|
||||||
|
efree(query_string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (full_post) {
|
||||||
|
PUTS(full_post);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,34 +182,98 @@ pm.max_children = 50
|
|||||||
;pm.max_requests = 500
|
;pm.max_requests = 500
|
||||||
|
|
||||||
; The URI to view the FPM status page. If this value is not set, no URI will be
|
; The URI to view the FPM status page. If this value is not set, no URI will be
|
||||||
; recognized as a status page. By default, the status page shows the following
|
; recognized as a status page. It shows the following informations:
|
||||||
; information:
|
|
||||||
; accepted conn - the number of request accepted by the pool;
|
|
||||||
; pool - the name of the pool;
|
; pool - the name of the pool;
|
||||||
; process manager - static or dynamic;
|
; process manager - static or dynamic;
|
||||||
|
; start time - the date and time FPM has started;
|
||||||
|
; start since - number of seconds since FPM has started;
|
||||||
|
; accepted conn - the number of request accepted by the pool;
|
||||||
|
; listen queue - the number of request in the queue of pending
|
||||||
|
; connections (see backlog in listen(2));
|
||||||
|
; max listen queue - the maximum number of requests in the queue
|
||||||
|
; of pending connections since FPM has started;
|
||||||
|
; listen queue len - the size of the socket queue of pending connections;
|
||||||
; idle processes - the number of idle processes;
|
; idle processes - the number of idle processes;
|
||||||
; active processes - the number of active processes;
|
; active processes - the number of active processes;
|
||||||
; total processes - the number of idle + active processes.
|
; total processes - the number of idle + active processes;
|
||||||
|
; max active processes - the maximum number of active processes since FPM
|
||||||
|
; has started;
|
||||||
; max children reached - number of times, the process limit has been reached,
|
; max children reached - number of times, the process limit has been reached,
|
||||||
; when pm tries to start more children (works only for
|
; when pm tries to start more children (works only for
|
||||||
; pm 'dynamic')
|
; pm 'dynamic');
|
||||||
; The values of 'idle processes', 'active processes' and 'total processes' are
|
; Value are updated in real time.
|
||||||
; updated each second. The value of 'accepted conn' is updated in real time.
|
|
||||||
; Example output:
|
; Example output:
|
||||||
; accepted conn: 12073
|
|
||||||
; pool: www
|
; pool: www
|
||||||
; process manager: static
|
; process manager: static
|
||||||
; idle processes: 35
|
; start time: 01/Jul/2011:17:53:49 +0200
|
||||||
; active processes: 65
|
; start since: 62636
|
||||||
; total processes: 100
|
; accepted conn: 190460
|
||||||
; max children reached: 1
|
; listen queue: 0
|
||||||
|
; max listen queue: 1
|
||||||
|
; listen queue len: 42
|
||||||
|
; idle processes: 4
|
||||||
|
; active processes: 11
|
||||||
|
; total processes: 15
|
||||||
|
; max active processes: 12
|
||||||
|
; max children reached: 0
|
||||||
|
;
|
||||||
; By default the status page output is formatted as text/plain. Passing either
|
; By default the status page output is formatted as text/plain. Passing either
|
||||||
; 'html', 'xml' or 'json' as a query string will return the corresponding output
|
; 'html', 'xml' or 'json' in the query string will return the corresponding
|
||||||
; syntax. Example:
|
; output syntax. Example:
|
||||||
; http://www.foo.bar/status
|
; http://www.foo.bar/status
|
||||||
; http://www.foo.bar/status?json
|
; http://www.foo.bar/status?json
|
||||||
; http://www.foo.bar/status?html
|
; http://www.foo.bar/status?html
|
||||||
; http://www.foo.bar/status?xml
|
; http://www.foo.bar/status?xml
|
||||||
|
;
|
||||||
|
; By default the status page only outputs short status. Passing 'full' in the
|
||||||
|
; query string will also return status for each pool process.
|
||||||
|
; Example:
|
||||||
|
; http://www.foo.bar/status?full
|
||||||
|
; http://www.foo.bar/status?json&full
|
||||||
|
; http://www.foo.bar/status?html&full
|
||||||
|
; http://www.foo.bar/status?xml&full
|
||||||
|
; The Full status returns for each process:
|
||||||
|
; pid - the PID of the process;
|
||||||
|
; state - the state of the process (Idle, Running, ...);
|
||||||
|
; start time - the date and time the process has started;
|
||||||
|
; start since - the number of seconds since the process has started;
|
||||||
|
; requests - the number of requests the process has served;
|
||||||
|
; request duration - the duration in µs of the requests;
|
||||||
|
; request method - the request method (GET, POST, ...);
|
||||||
|
; request URI - the request URI with the query string;
|
||||||
|
; content length - the content length of the request (only with POST);
|
||||||
|
; user - the user (PHP_AUTH_USER) (or '-' if not set);
|
||||||
|
; script - the main script called (or '-' if not set);
|
||||||
|
; last request cpu - the %cpu the last request consumed
|
||||||
|
; it's always 0 if the process is not in Idle state
|
||||||
|
; because CPU calculation is done when the request
|
||||||
|
; processing has terminated;
|
||||||
|
; last request memory - the max amount of memory the last request consumed
|
||||||
|
; it's always 0 if the process is not in Idle state
|
||||||
|
; because memory calculation is done when the request
|
||||||
|
; processing has terminated;
|
||||||
|
; If the process is in Idle state, then informations are related to the
|
||||||
|
; last request the process has served. Otherwise informations are related to
|
||||||
|
; the current request being served.
|
||||||
|
; Example output:
|
||||||
|
; ************************
|
||||||
|
; pid: 31330
|
||||||
|
; state: Running
|
||||||
|
; start time: 01/Jul/2011:17:53:49 +0200
|
||||||
|
; start since: 63087
|
||||||
|
; requests: 12808
|
||||||
|
; request duration: 1250261
|
||||||
|
; request method: GET
|
||||||
|
; request URI: /test_mem.php?N=10000
|
||||||
|
; content length: 0
|
||||||
|
; user: -
|
||||||
|
; script: /home/fat/web/docs/php/test_mem.php
|
||||||
|
; last request cpu: 0.00
|
||||||
|
; last request memory: 0
|
||||||
|
;
|
||||||
|
; Note: There is a real-time FPM status monitoring sample web page available
|
||||||
|
; It's available in: @EXPANDED_DATADIR@/fpm/status.html
|
||||||
|
;
|
||||||
; Note: The value must start with a leading slash (/). The value can be
|
; Note: The value must start with a leading slash (/). The value can be
|
||||||
; anything, but it may not be a good idea to use the .php extension or it
|
; anything, but it may not be a good idea to use the .php extension or it
|
||||||
; may conflict with a real PHP file.
|
; may conflict with a real PHP file.
|
||||||
|
459
sapi/fpm/status.html
Normal file
459
sapi/fpm/status.html
Normal file
@ -0,0 +1,459 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<!--
|
||||||
|
$Id$
|
||||||
|
(c) 2011 Jerome Loyet
|
||||||
|
The PHP License, version 3.01
|
||||||
|
This is sample real-time status page for FPM. You can change it to better feet your needs.
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
||||||
|
<style type="text/css">
|
||||||
|
body {background-color: #ffffff; color: #000000;}
|
||||||
|
body, td, th, h1, h2 {font-family: sans-serif;}
|
||||||
|
pre {margin: 0px; font-family: monospace;}
|
||||||
|
a:link {color: #000099; text-decoration: none; background-color: #ffffff;}
|
||||||
|
a:hover {text-decoration: underline;}
|
||||||
|
table {border-collapse: collapse;}
|
||||||
|
.center {text-align: center;}
|
||||||
|
.center table { margin-left: auto; margin-right: auto; text-align: left;}
|
||||||
|
.center th { text-align: center !important; }
|
||||||
|
td, th { border: 1px solid #000000; font-size: 75%; vertical-align: baseline;}
|
||||||
|
h1 {font-size: 150%;}
|
||||||
|
h2 {font-size: 125%;}
|
||||||
|
.p {text-align: left;}
|
||||||
|
.e {background-color: #ccccff; font-weight: bold; color: #000000;}
|
||||||
|
.h {background-color: #9999cc; font-weight: bold; color: #000000;}
|
||||||
|
|
||||||
|
.v {background-color: #cccccc; color: #000000;}
|
||||||
|
.w {background-color: #ccccff; color: #000000;}
|
||||||
|
|
||||||
|
.h th {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
img {float: right; border: 0px;}
|
||||||
|
hr {width: 600px; background-color: #cccccc; border: 0px; height: 1px; color: #000000;}
|
||||||
|
</style>
|
||||||
|
<title>PHP-FPM status page</title>
|
||||||
|
<meta name="ROBOTS" content="NOINDEX,NOFOLLOW,NOARCHIVE" /></head>
|
||||||
|
<body>
|
||||||
|
<div class="center">
|
||||||
|
<table border="0" cellpadding="3" width="95%">
|
||||||
|
<tr class="h">
|
||||||
|
<td>
|
||||||
|
<a href="http://www.php.net/"><img border="0" src="https://static.php.net/www.php.net/images/php.gif" alt="PHP Logo" /></a><h1 class="p">PHP-FPM real-time status page</h1>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<br />
|
||||||
|
<table border="0" cellpadding="3" width="95%">
|
||||||
|
<tr><td class="e">Status URL</td><td class="v"><input type="text" id="url" size="45" /></td></tr>
|
||||||
|
<tr><td class="e">Ajax status</td><td class="v" id="status"></td></tr>
|
||||||
|
<tr><td class="e">Refresh Rate</td><td class="v"><input type="text" id="rate" value="1" /></td></tr>
|
||||||
|
<tr>
|
||||||
|
<td class="e">Actions</td>
|
||||||
|
<td class="v">
|
||||||
|
<button onclick="javascript:refresh();">Manual Refresh</button>
|
||||||
|
<button id="play" onclick="javascript:playpause();">Play</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<h1>Pool Status</h1>
|
||||||
|
<table border="0" cellpadding="3" width="95%" id="short">
|
||||||
|
<tr style="display: none;"><td> </td></tr>
|
||||||
|
</table>
|
||||||
|
<h1>Active Processes status</h1>
|
||||||
|
<table border="0" cellpadding="3" width="95%" id="active">
|
||||||
|
<tr class="h"><th>PID↓</th><th>Start Time</th><th>Start Since</th><th>Requests Served</th><th>Request Duration</th><th>Request method</th><th>Request URI</th><th>Content Length</th><th>User</th><th>Script</th></tr>
|
||||||
|
</table>
|
||||||
|
<h1>Idle Processes status</h1>
|
||||||
|
<table border="0" cellpadding="3" width="95%" id="idle">
|
||||||
|
<tr class="h"><th>PID↓</th><th>Start Time</th><th>Start Since</th><th>Requests Served</th><th>Request Duration</th><th>Request method</th><th>Request URI</th><th>Content Length</th><th>User</th><th>Script</th><th>Last Request %CPU</th><th>Last Request Memory</th></tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<a href="http://validator.w3.org/check?uri=referer">
|
||||||
|
<img src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0 Transitional" height="31" width="88" />
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<script type="text/javascript">
|
||||||
|
<!--
|
||||||
|
var xhr_object = null;
|
||||||
|
var doc_url = document.getElementById("url");
|
||||||
|
var doc_rate = document.getElementById("rate");
|
||||||
|
var doc_status = document.getElementById("status");
|
||||||
|
var doc_play = document.getElementById("play");
|
||||||
|
var doc_short = document.getElementById("short");
|
||||||
|
var doc_active = document.getElementById("active");
|
||||||
|
var doc_idle = document.getElementById("idle");
|
||||||
|
var rate = 0;
|
||||||
|
var play=0;
|
||||||
|
var delay = 1000;
|
||||||
|
var order_active_index = 0;
|
||||||
|
var order_active_reverse = 0;
|
||||||
|
var order_idle_index = 0;
|
||||||
|
var order_idle_reverse = 0;
|
||||||
|
var sort_index;
|
||||||
|
var sort_order;
|
||||||
|
|
||||||
|
doc_url.value = location.protocol + '//' + location.host + "/status?json&full";
|
||||||
|
|
||||||
|
ths = document.getElementsByTagName("th");
|
||||||
|
for (var i=0; i<ths.length; i++) {
|
||||||
|
var th = ths[i];
|
||||||
|
if (th.parentNode.className == "h") {
|
||||||
|
th.onclick = function() { order(this); return false; };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
xhr_object = create_ajax();
|
||||||
|
|
||||||
|
function create_ajax() {
|
||||||
|
if (window.XMLHttpRequest) {
|
||||||
|
return new XMLHttpRequest();
|
||||||
|
}
|
||||||
|
var names = [
|
||||||
|
"Msxml2.XMLHTTP.6.0",
|
||||||
|
"Msxml2.XMLHTTP.3.0",
|
||||||
|
"Msxml2.XMLHTTP",
|
||||||
|
"Microsoft.XMLHTTP"
|
||||||
|
];
|
||||||
|
for(var i in names)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return new ActiveXObject(names[i]);
|
||||||
|
} catch(e){}
|
||||||
|
}
|
||||||
|
alert("Browser not compatible ...");
|
||||||
|
}
|
||||||
|
|
||||||
|
function order(cell) {
|
||||||
|
var table;
|
||||||
|
|
||||||
|
if (cell.constructor != HTMLTableCellElement && cell.constructor != HTMLTableHeaderCellElement) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
table = cell.parentNode.parentNode.parentNode;
|
||||||
|
|
||||||
|
if (table == doc_active) {
|
||||||
|
if (order_active_index == cell.cellIndex) {
|
||||||
|
if (order_active_reverse == 0) {
|
||||||
|
cell.innerHTML = cell.innerHTML.replace(/.$/, "↑");
|
||||||
|
order_active_reverse = 1;
|
||||||
|
} else {
|
||||||
|
cell.innerHTML = cell.innerHTML.replace(/.$/, "↓");
|
||||||
|
order_active_reverse = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var c = doc_active.rows[0].cells[order_active_index];
|
||||||
|
c.innerHTML = c.innerHTML.replace(/.$/, "");
|
||||||
|
cell.innerHTML = cell.innerHTML.replace(/$/, order_active_reverse == 0 ? "↓" : "↑");
|
||||||
|
order_active_index = cell.cellIndex;
|
||||||
|
}
|
||||||
|
reorder(table, order_active_index, order_active_reverse);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (table == doc_idle) {
|
||||||
|
if (order_idle_index == cell.cellIndex) {
|
||||||
|
if (order_idle_reverse == 0) {
|
||||||
|
cell.innerHTML = cell.innerHTML.replace(/.$/, "↑");
|
||||||
|
order_idle_reverse = 1;
|
||||||
|
} else {
|
||||||
|
cell.innerHTML = cell.innerHTML.replace(/.$/, "↓");
|
||||||
|
order_idle_reverse = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var c = doc_idle.rows[0].cells[order_idle_index];
|
||||||
|
c.innerHTML = c.innerHTML.replace(/.$/, "");
|
||||||
|
cell.innerHTML = cell.innerHTML.replace(/$/, order_idle_reverse == 0 ? "↓" : "↑");
|
||||||
|
order_idle_index = cell.cellIndex;
|
||||||
|
}
|
||||||
|
reorder(table, order_idle_index, order_idle_reverse);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function reorder(table, index, order) {
|
||||||
|
var rows = [];
|
||||||
|
while (table.rows.length > 1) {
|
||||||
|
rows.push(table.rows[1]);
|
||||||
|
table.deleteRow(1);
|
||||||
|
}
|
||||||
|
sort_index = index;
|
||||||
|
sort_order = order;
|
||||||
|
rows.sort(sort_table);
|
||||||
|
for (var i in rows) {
|
||||||
|
table.appendChild(rows[i]);
|
||||||
|
}
|
||||||
|
var odd = 1;
|
||||||
|
for (var i=1; i<table.rows.length; i++) {
|
||||||
|
table.rows[i].className = odd++ % 2 == 0 ? "v" : "w";
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
function sort_table(a, b) {
|
||||||
|
if (a.cells[0].tagName == "TH") return -1;
|
||||||
|
if (b.cells[0].tagName == "TH") return 1;
|
||||||
|
|
||||||
|
if (a.cells[sort_index].__search_t == 0) { /* integer */
|
||||||
|
if (!sort_order) return a.cells[sort_index].__search_v - b.cells[sort_index].__search_v;
|
||||||
|
return b.cells[sort_index].__search_v - a.cells[sort_index].__search_v;;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* string */
|
||||||
|
if (!sort_order) return a.cells[sort_index].__search_v.localeCompare(b.cells[sort_index].__search_v);
|
||||||
|
else return b.cells[sort_index].__search_v.localeCompare(a.cells[sort_index].__search_v);
|
||||||
|
}
|
||||||
|
|
||||||
|
function playpause() {
|
||||||
|
rate = 0;
|
||||||
|
if (play) {
|
||||||
|
play = 0;
|
||||||
|
doc_play.innerHTML = "Play";
|
||||||
|
doc_rate.disabled = false;
|
||||||
|
} else {
|
||||||
|
delay = parseInt(doc_rate.value);
|
||||||
|
if (!delay || delay < 1) {
|
||||||
|
doc_status.innerHTML = "Not valid 'refresh' value";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
play = 1;
|
||||||
|
doc_rate.disabled = true;
|
||||||
|
doc_play.innerHTML = "Pause";
|
||||||
|
setTimeout("callback()", delay * 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function refresh() {
|
||||||
|
if (xhr_object == null) return;
|
||||||
|
if (xhr_object.readyState > 0 && xhr_object.readyState < 4) {
|
||||||
|
return; /* request is running */
|
||||||
|
}
|
||||||
|
xhr_object.open("GET", doc_url.value, true);
|
||||||
|
xhr_object.onreadystatechange = function() {
|
||||||
|
switch(xhr_object.readyState) {
|
||||||
|
case 0:
|
||||||
|
doc_status.innerHTML = "uninitialized";
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
doc_status.innerHTML = "loading ...";
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
doc_status.innerHTML = "loaded";
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
doc_status.innerHTML = "interactive";
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
doc_status.innerHTML = "complete";
|
||||||
|
if (xhr_object.status == 200) {
|
||||||
|
fpm_status(xhr_object.responseText);
|
||||||
|
} else {
|
||||||
|
doc_status.innerHTML = "Error " + xhr_object.status;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xhr_object.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
function callback() {
|
||||||
|
if (!play) return;
|
||||||
|
refresh();
|
||||||
|
setTimeout("callback()", delay * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function fpm_status(txt) {
|
||||||
|
var json = null;
|
||||||
|
|
||||||
|
while (doc_short.rows.length > 0) {
|
||||||
|
doc_short.deleteRow(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (doc_active.rows.length > 1) {
|
||||||
|
doc_active.deleteRow(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (doc_idle.rows.length > 1) {
|
||||||
|
doc_idle.deleteRow(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
json = JSON.parse(txt);
|
||||||
|
} catch (e) {
|
||||||
|
doc_status.innerHTML = "Error while parsing json: '" + e + "': <br /><pre>" + txt + "</pre>";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var key in json) {
|
||||||
|
if (key == "processes") continue;
|
||||||
|
if (key == "state") continue;
|
||||||
|
var row = doc_short.insertRow(doc_short.rows.length);
|
||||||
|
var value = json[key];
|
||||||
|
if (key == "start time") {
|
||||||
|
value = new Date(value * 1000).toLocaleString();
|
||||||
|
}
|
||||||
|
if (key == "start since") {
|
||||||
|
value = time_s(value);
|
||||||
|
}
|
||||||
|
var cell = row.insertCell(row.cells.length);
|
||||||
|
cell.className = "e";
|
||||||
|
cell.innerHTML = key;
|
||||||
|
|
||||||
|
cell = row.insertCell(row.cells.length);
|
||||||
|
cell.className = "v";
|
||||||
|
cell.innerHTML = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json.processes) {
|
||||||
|
process_full(json.processes, doc_active, "Idle", 0, 0);
|
||||||
|
reorder(doc_active, order_active_index, order_active_reverse);
|
||||||
|
|
||||||
|
process_full(json.processes, doc_idle, "Idle", 1, 1);
|
||||||
|
reorder(doc_idle, order_idle_index, order_idle_reverse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function process_full(processes, table, state, equal, cpumem) {
|
||||||
|
var odd = 1;
|
||||||
|
|
||||||
|
for (var i in processes) {
|
||||||
|
var proc = processes[i];
|
||||||
|
if ((equal && proc.state == state) || (!equal && proc.state != state)) {
|
||||||
|
var c = odd++ % 2 == 0 ? "v" : "w";
|
||||||
|
var row = table.insertRow(-1);
|
||||||
|
row.className = c;
|
||||||
|
row.insertCell(-1).innerHTML = proc.pid;
|
||||||
|
row.cells[row.cells.length - 1].__search_v = proc.pid;
|
||||||
|
row.cells[row.cells.length - 1].__search_t = 0;
|
||||||
|
|
||||||
|
row.insertCell(-1).innerHTML = date(proc['start time'] * 1000);;
|
||||||
|
row.cells[row.cells.length - 1].__search_v = proc['start time'];
|
||||||
|
row.cells[row.cells.length - 1].__search_t = 0;
|
||||||
|
|
||||||
|
row.insertCell(-1).innerHTML = time_s(proc['start since']);
|
||||||
|
row.cells[row.cells.length - 1].__search_v = proc['start since'];
|
||||||
|
row.cells[row.cells.length - 1].__search_t = 0;
|
||||||
|
|
||||||
|
row.insertCell(-1).innerHTML = proc.requests;
|
||||||
|
row.cells[row.cells.length - 1].__search_v = proc.requests;
|
||||||
|
row.cells[row.cells.length - 1].__search_t = 0;
|
||||||
|
|
||||||
|
row.insertCell(-1).innerHTML = time_u(proc['request duration']);
|
||||||
|
row.cells[row.cells.length - 1].__search_v = proc['request duration'];
|
||||||
|
row.cells[row.cells.length - 1].__search_t = 0;
|
||||||
|
|
||||||
|
row.insertCell(-1).innerHTML = proc['request method'];
|
||||||
|
row.cells[row.cells.length - 1].__search_v = proc['request method'];
|
||||||
|
row.cells[row.cells.length - 1].__search_t = 1;
|
||||||
|
|
||||||
|
row.insertCell(-1).innerHTML = proc['request uri'];
|
||||||
|
row.cells[row.cells.length - 1].__search_v = proc['request uri'];
|
||||||
|
row.cells[row.cells.length - 1].__search_t = 1;
|
||||||
|
|
||||||
|
row.insertCell(-1).innerHTML = proc['content length'];
|
||||||
|
row.cells[row.cells.length - 1].__search_v = proc['content length'];
|
||||||
|
row.cells[row.cells.length - 1].__search_t = 0;
|
||||||
|
|
||||||
|
row.insertCell(-1).innerHTML = proc.user;
|
||||||
|
row.cells[row.cells.length - 1].__search_v = proc.user;
|
||||||
|
row.cells[row.cells.length - 1].__search_t = 1;
|
||||||
|
|
||||||
|
row.insertCell(-1).innerHTML = proc.script;
|
||||||
|
row.cells[row.cells.length - 1].__search_v = proc.script;
|
||||||
|
row.cells[row.cells.length - 1].__search_t = 1;
|
||||||
|
|
||||||
|
if (cpumem) {
|
||||||
|
row.insertCell(-1).innerHTML = cpu(proc['last request cpu']);
|
||||||
|
row.cells[row.cells.length - 1].__search_v = proc['last request cpu'];
|
||||||
|
row.cells[row.cells.length - 1].__search_t = 0;
|
||||||
|
|
||||||
|
row.insertCell(-1).innerHTML = memory(proc['last request memory']);
|
||||||
|
row.cells[row.cells.length - 1].__search_v = proc['last request memory'];
|
||||||
|
row.cells[row.cells.length - 1].__search_t = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function date(d) {
|
||||||
|
var t = new Date(d);
|
||||||
|
var r = "";
|
||||||
|
|
||||||
|
r += (t.getDate() < 10 ? '0' : '') + t.getDate();
|
||||||
|
r += '/';
|
||||||
|
r += (t.getMonth() + 1 < 10 ? '0' : '') + (t.getMonth() + 1);
|
||||||
|
r += '/';
|
||||||
|
r += t.getFullYear();
|
||||||
|
r += ' ';
|
||||||
|
r += (t.getHours() < 10 ? '0' : '') + t.getHours();
|
||||||
|
r += ':';
|
||||||
|
r += (t.getMinutes() < 10 ? '0' : '') + t.getMinutes();
|
||||||
|
r += ':';
|
||||||
|
r += (t.getSeconds() < 10 ? '0' : '') + t.getSeconds();
|
||||||
|
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
function cpu(c) {
|
||||||
|
if (c == 0) return 0;
|
||||||
|
return c + "%";
|
||||||
|
}
|
||||||
|
|
||||||
|
function memory(mem) {
|
||||||
|
if (mem == 0) return 0;
|
||||||
|
if (mem < 1024) {
|
||||||
|
return mem + "B";
|
||||||
|
}
|
||||||
|
if (mem < 1024 * 1024) {
|
||||||
|
return mem/1024 + "KB";
|
||||||
|
}
|
||||||
|
if (mem < 1024*1024*1024) {
|
||||||
|
return mem/1024/1024 + "MB";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function time_s(t) {
|
||||||
|
var r = "";
|
||||||
|
if (t < 60) {
|
||||||
|
return t + 's';
|
||||||
|
}
|
||||||
|
|
||||||
|
r = (t % 60) + 's';
|
||||||
|
t = Math.floor(t / 60);
|
||||||
|
if (t < 60) {
|
||||||
|
return t + 'm ' + r;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = (t % 60) + 'm ' + r;
|
||||||
|
t = Math.floor(t/60);
|
||||||
|
|
||||||
|
if (t < 24) {
|
||||||
|
return t + 'h ' + r;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.floor(t/24) + 'd ' + (t % 24) + 'h ' + t;
|
||||||
|
}
|
||||||
|
|
||||||
|
function time_u(t) {
|
||||||
|
var r = "";
|
||||||
|
if (t < 1000) {
|
||||||
|
return t + 'µs'
|
||||||
|
}
|
||||||
|
|
||||||
|
r = (t % 1000) + 'µs';
|
||||||
|
t = Math.floor(t / 1000);
|
||||||
|
if (t < 1000) {
|
||||||
|
return t + 'ms ' + r;
|
||||||
|
}
|
||||||
|
|
||||||
|
return time_s(Math.floor(t/1000)) + ' ' + (t%1000) + 'ms ' + r;
|
||||||
|
}
|
||||||
|
-->
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user