Adds some more statistical data to the output of the penctl command "New" commands are cstatus and connstatus --- pen.c 2008-05-03 09:29:36.000000000 +0200 +++ pen.c-info 2009-01-12 02:41:00.000000000 +0100 @@ -102,6 +102,8 @@ int port; struct in_addr addr; int c; /* connections */ + unsigned long long totalconns; /* total connections */ + unsigned long long hits; /* total hits */ int weight; /* default 1 */ int prio; int maxc; /* max connections, soft limit */ @@ -139,6 +141,8 @@ static int loopflag; static int exit_enabled = 0; +static time_t starttime = 0; /* when server was started */ +static unsigned long long hits = 0; /* total number of hits including emergs */ static int clients_max = CLIENTS_MAX; static int servers_max = SERVERS_MAX; @@ -728,6 +732,7 @@ inet_ntoa(cli), i, ch); } servers[ch].c++; + servers[ch].totalconns++; return i; } @@ -933,6 +938,10 @@ } if (debuglevel > 2) dump(b, rc); + hits++; + servers[serverindex].hits++; + clients[conns[i].clt].last = time(NULL); /* really needed? */ + if (logfp) { log_request(logfp, i, b, rc); if (debuglevel > 2) log_request(stderr, i, b, rc); @@ -1459,6 +1468,24 @@ fclose(fp); } +static char *BytePowered(unsigned long long bytes) +{ + char tmpstr[25]; + if (bytes > 10240) { + char powers[8] = "KMGTPEZY"; + int bytepower = -1; + while (bytes > 10240) { + bytes = bytes / 1024; + bytepower++; + } + sprintf(tmpstr, "%llu%cB", bytes, powers[bytepower]); + return strdup(tmpstr); + } else { + sprintf(tmpstr, "%llub", bytes); + return strdup(tmpstr); + } +} + static void do_cmd(char *b, void (*output)(char *, void *), void *op) { char *p, *q; @@ -1677,6 +1704,54 @@ servers[n].sx, servers[n].rx); output(b, op); } + } else if (!strcmp(p, "cstatus")) { + unsigned long long totalconns = 0; + char *pbytesx; + char *pbyterx; + for (n = 0; n < nservers; n++) { + pbytesx = BytePowered(servers[n].sx); + pbyterx = BytePowered(servers[n].rx); + sprintf(b, "%d addr %s port %d status %d conn %d max %d hard %d weight %d prio %d sx %s rx %s tcon %llu hits %llu\n", + n, inet_ntoa(servers[n].addr), servers[n].port, servers[n].status, + servers[n].c, servers[n].maxc, servers[n].hard, + servers[n].weight, servers[n].prio, + pbytesx, pbyterx, servers[n].totalconns, servers[n].hits); + free(pbytesx); free(pbyterx); + totalconns += servers[n].totalconns; // TODO overflow :> + output(b, op); + } + + int now = time(NULL); + int clients_active = 0; + for (n = 0; n < clients_max; n++) { + if ( clients[n].last == 0 ) continue; // timesaving here? + if ( (now - clients[n].last) <= tracking_time ) clients_active++; + } + sprintf(b, "Clients last %ds: %d/%d\nConnections active: %d/%d (last: %d)\n", tracking_time, clients_active, clients_max, connections_used, connections_max, connections_last); + output(b, op); + + int duration = time(NULL) - starttime, persec = 0; + persec = (hits / duration); + char nowstr[80]; + strftime(nowstr, sizeof(nowstr), "%Y-%m-%d %H:%M:%S", localtime(&starttime) ); + sprintf(b, "Total Hits since start (%s): %llu (^= %d/s) totalconns: %llu\n", nowstr, hits, persec, totalconns); + output(b, op); + } else if (!strcmp(p, "connstatus")) { + time_t now=time(NULL); + sprintf(b, "con\tdownfd\tupfd\tpendd\tpendu\tclient\tserver\tclientip\tage\tlastaccess\tcno\tconnects\n"); + output(b, op); + for (n = 0; n < connections_max; n++) { + if (conns[n].downfd == -1) continue; + sprintf(b,"%d\t%d\t%d\t%d\t%d\t%d\t%d\t%s\t%ld\t%ld\t%d\t%ld\t\n", + n, conns[n].downfd, conns[n].upfd, + conns[n].downn, conns[n].upn, + conns[n].clt, conns[n].index, + inet_ntoa(clients[conns[n].clt].addr), (long)(now-clients[conns[n].clt].last), + clients[conns[n].clt].last, + clients[conns[n].clt].cno, clients[conns[n].clt].connects + ); + output(b, op); + } } else if (!strcmp(p, "status")) { p = webfile; webfile = "/tmp/webfile.html"; @@ -2779,6 +2854,8 @@ fclose(pidfp); } + starttime = time(NULL); + #ifdef HAVE_KQUEUE if (use_kqueue) mainloop_kqueue(); #else