#include "stats.h" static pyfcgi_stats_t pyfcgi_stats; int pyfcgi_stats_init() { struct sigaction act; struct itimerspec timeout; memset(&pyfcgi_stats, 0, sizeof(pyfcgi_stats_t)); if(timer_create(CLOCK_REALTIME, NULL, &(pyfcgi_stats.timerid)) < 0) { pyfcgi_log(LOG_ERR, "Unable to create timer for stats collecting : %s", strerror(errno)); goto err; } act.sa_handler = pyfcgi_stats_collector; sigemptyset(&act.sa_mask); act.sa_flags = 0; act.sa_restorer = NULL; if(sigaction(SIGALRM, &act, &(pyfcgi_stats.oldact)) < 0) { pyfcgi_log(LOG_ERR, "Unable to register signal handler for stats collecting : %s", strerror(errno)); goto err_deltimer; } timeout.it_value.tv_sec = 1; timeout.it_value.tv_nsec = 0; timeout.it_interval = timeout.it_value; if(timer_settime(pyfcgi_stats.timerid, 0, &timeout, NULL) < 0) { pyfcgi_log(LOG_ERR, "Unable to start timer for stats collecting : %s", strerror(errno)); goto err_sigrestore; } return 0; err_sigrestore: sigaction(SIGALRM, &(pyfcgi_stats.oldact), NULL); err_deltimer: timer_delete(pyfcgi_stats.timerid); err: memset(&pyfcgi_stats, 0, sizeof(pyfcgi_stats_t)); return -1; } void pyfcgi_stats_collector(int signum) { int ret; pyfcgi_stats_t *stats; stats = &pyfcgi_stats; stats->reqs[stats->cur_req] = 0; while( !(ret = sem_trywait(PyFCGI_SEM(SEM_WREQS).sem)) ) { stats->reqs[stats->cur_req]++; } pyfcgi_log(LOG_DEBUG, "s#%d %d req/s", pyfcgi_stats.cur_req, pyfcgi_stats.reqs[stats->cur_req]); stats->cur_req++; stats->cur_req %= PYFCGI_STATS_REQS_SAMPLES; return; } size_t pyfcgi_stats_format() { char uptime[80], since[80]; char ds[18], hs[5], ms[5], ss[5]; unsigned long diff, d; short s, m, h; struct tm *tm; tm = localtime(&PyFCGI_conf.context.uptime); if(!strftime(since, 80, "%F %H:%M:%S%z", tm)) { pyfcgi_log(LOG_WARNING, "Date too long !"); strcpy(since, "???"); } diff = (unsigned long)difftime(time(NULL), PyFCGI_conf.context.uptime); s = diff%60; diff /= 60; m = diff % 60; diff /= 60; h = diff % 24; diff /=24; d = diff; if(d) { snprintf(ds, 18, "%02ldd ", d); } else { ds[0] = '\0'; } if(h || *ds) { snprintf(hs, 5, "%02dh ", h); } else { hs[0] = '\0'; } if(m || *hs) { snprintf(ms, 5, "%02dm ", m); } else { ms[0] = '\0'; } if(s || *ms) { snprintf(ss, 5, "%02ds ", s); } else { ss[0] = '\0'; } snprintf(uptime, 80, "%s%s%s%s", ds, hs, ms, ss); pyfcgi_stats.buff_ptr = 0; pyfcgi_stats_buffprintf("%s\nUptime : %s since %s\n", PACKAGE_STRING, uptime, since); // Request counter stats formating double r15, r10, r5, r1, rtmp; unsigned long stmp; // stores a 60s req sum int i, cur_req, cur_rs, idx; r15 = r10 = r5 = r1 = stmp = 0; cur_req = pyfcgi_stats.cur_req; //Block interrupt/ALARM ?? for(i=0; i= left) { if(pyfcgi_stats_reqbuff(pyfcgi_stats.buff_ptr + fsz) < 0) { exit(PYFCGI_ERR); } continue; } pyfcgi_stats.buff_ptr += fsz; break; } } int pyfcgi_stats_reqbuff(size_t sz) { void *tmp; if(sz <= pyfcgi_stats.buff_len) { return 0; } sz = ((sz>>11)+1)<<11; if( !(tmp = realloc(pyfcgi_stats.buff, sz)) ) { pyfcgi_log(LOG_ALERT, "Unable to reallocate stats buffer : %s", strerror(errno)); return -1; } pyfcgi_stats.buff_len = sz; pyfcgi_stats.buff = tmp; return 0; } const char *pyfcgi_stats_buff(const char **buff, size_t* len) { *buff = pyfcgi_stats.buff; *len = pyfcgi_stats.buff_ptr; return *buff; }