1
0
Fork 0
mirror of https://libwebsockets.org/repo/libwebsockets synced 2025-03-15 17:24:44 +00:00

server-status: add proc statm and switch to vhost protocol timer

This commit is contained in:
Andy Green 2019-02-18 09:02:33 +08:00
parent f74326e6e1
commit fb90b04e97
4 changed files with 123 additions and 88 deletions

View file

@ -164,9 +164,9 @@ lws_json_dump_context(const struct lws_context *context, char *buf, int len,
char *orig = buf, *end = buf + len - 1, first = 1;
const struct lws_vhost *vh = context->vhost_list;
const struct lws_context_per_thread *pt;
time_t t = time(NULL);
int n, listening = 0, cgi_count = 0;
int n, listening = 0, cgi_count = 0, fd;
struct lws_conn_stats cs;
time_t t = time(NULL);
double d = 0;
#ifdef LWS_WITH_CGI
struct lws_cgi * const *pcgi;
@ -196,6 +196,22 @@ lws_json_dump_context(const struct lws_context *context, char *buf, int len,
}
#endif
fd = lws_open("/proc/self/statm", LWS_O_RDONLY);
if (fd >= 0) {
char contents[96], pure[96];
n = read(fd, contents, sizeof(contents) - 1);
if (n > 0) {
contents[n] = '\0';
if (contents[n - 1] == '\n')
contents[--n] = '\0';
lws_json_purify(pure, contents, sizeof(pure));
buf += lws_snprintf(buf, end - buf,
"\"statm\": \"%s\",\n", pure);
}
close(fd);
}
buf += lws_snprintf(buf, end - buf, "\"contexts\":[\n");
buf += lws_snprintf(buf, end - buf, "{ "

View file

@ -1,7 +1,7 @@
/*
* libwebsockets-test-server - libwebsockets test implementation
*
* Copyright (C) 2010-2016 Andy Green <andy@warmcat.com>
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
*
* This file is made available under the Creative Commons CC0 1.0
* Universal Public Domain Dedication.
@ -37,16 +37,19 @@ struct lws_ss_dumps {
int length;
};
struct per_session_data__server_status {
struct pss {
int ver;
int pos;
};
struct per_vhost_data__lws_server_status {
struct vhd {
struct lws_context *context;
struct lws_vhost *vhost;
const struct lws_protocols *protocol;
int hide_vhosts;
int tow_flag;
int period_us;
int period_s;
int clients;
struct lws_ss_dumps d;
struct lws_ss_filepath *fp;
};
@ -54,33 +57,23 @@ struct per_vhost_data__lws_server_status {
static const struct lws_protocols protocols[1];
static void
update(struct per_vhost_data__lws_server_status *v)
update(struct vhd *v)
{
struct lws_ss_filepath *fp;
char *p = v->d.buf + LWS_PRE, contents[256], pure[256];
int n, l, first = 1, fd;
char contents[256], pure[256], *p = v->d.buf + LWS_PRE,
*end = v->d.buf + sizeof(v->d.buf) - LWS_PRE - 1;
int n, first = 1, fd;
l = sizeof(v->d.buf) - LWS_PRE - 1;
n = lws_snprintf(p, l, "{\"i\":");
p += n;
l -= n;
n = lws_json_dump_context(v->context, p, l, v->hide_vhosts);
p += n;
l -= n;
n = lws_snprintf(p, l, ", \"files\": [");
p += n;
l -= n;
p += lws_snprintf(p, lws_ptr_diff(end, p), "{\"i\":");
p += lws_json_dump_context(v->context, p, lws_ptr_diff(end, p),
v->hide_vhosts);
p += lws_snprintf(p, lws_ptr_diff(end, p), ", \"files\": [");
fp = v->fp;
while (fp) {
if (!first) {
n = lws_snprintf(p, l, ",");
p += n;
l -= n;
}
if (!first)
p += lws_snprintf(p, lws_ptr_diff(end, p), ",");
fd = lws_open(fp->filepath, LWS_O_RDONLY);
if (fd >= 0) {
n = read(fd, contents, sizeof(contents) - 1);
@ -88,20 +81,17 @@ update(struct per_vhost_data__lws_server_status *v)
contents[n] = '\0';
lws_json_purify(pure, contents, sizeof(pure));
n = lws_snprintf(p, l,
p += lws_snprintf(p, lws_ptr_diff(end, p),
"{\"path\":\"%s\",\"val\":\"%s\"}",
fp->filepath, pure);
p += n;
l -= n;
first = 0;
}
close(fd);
}
fp = fp->next;
}
n = lws_snprintf(p, l, "]}");
p += n;
p += lws_snprintf(p, lws_ptr_diff(end, p), "]}");
v->d.length = p - (v->d.buf + LWS_PRE);
lws_callback_on_writable_all_protocol(v->context, &protocols[0]);
@ -113,8 +103,7 @@ callback_lws_server_status(struct lws *wsi, enum lws_callback_reasons reason,
{
const struct lws_protocol_vhost_options *pvo =
(const struct lws_protocol_vhost_options *)in;
struct per_vhost_data__lws_server_status *v =
(struct per_vhost_data__lws_server_status *)
struct vhd *v = (struct vhd *)
lws_protocol_vh_priv_get(lws_get_vhost(wsi),
lws_get_protocol(wsi));
struct lws_ss_filepath *fp, *fp1, **fp_old;
@ -124,8 +113,26 @@ callback_lws_server_status(struct lws *wsi, enum lws_callback_reasons reason,
case LWS_CALLBACK_ESTABLISHED:
lwsl_info("%s: LWS_CALLBACK_ESTABLISHED\n", __func__);
lws_set_timer_usecs(wsi, v->period_us);
lws_callback_on_writable(wsi);
if (!v->clients++) {
lws_timed_callback_vh_protocol(v->vhost, v->protocol,
LWS_CALLBACK_USER, v->period_s);
lwsl_info("%s: starting updates\n", __func__);
}
update(v);
break;
case LWS_CALLBACK_CLOSED:
if (!--v->clients)
lwsl_notice("%s: stopping updates\n", __func__);
break;
case LWS_CALLBACK_USER:
update(v);
if (v->clients)
lws_timed_callback_vh_protocol(v->vhost, v->protocol,
LWS_CALLBACK_USER, v->period_s);
break;
case LWS_CALLBACK_PROTOCOL_INIT: /* per vhost */
@ -133,11 +140,10 @@ callback_lws_server_status(struct lws *wsi, enum lws_callback_reasons reason,
break;
lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi),
lws_get_protocol(wsi),
sizeof(struct per_vhost_data__lws_server_status));
v = (struct per_vhost_data__lws_server_status *)
lws_protocol_vh_priv_get(lws_get_vhost(wsi),
lws_get_protocol(wsi));
lws_get_protocol(wsi),
sizeof(struct vhd));
v = (struct vhd *)lws_protocol_vh_priv_get(lws_get_vhost(wsi),
lws_get_protocol(wsi));
fp_old = &v->fp;
@ -145,9 +151,9 @@ callback_lws_server_status(struct lws *wsi, enum lws_callback_reasons reason,
if (!strcmp(pvo->name, "hide-vhosts"))
v->hide_vhosts = atoi(pvo->value);
if (!strcmp(pvo->name, "update-ms"))
v->period_us = atoi(pvo->value) * 1000;
v->period_s = (atoi(pvo->value) + 500) / 1000;
else
v->period_us = 5 * 1000 * 1000;
v->period_s = 5;
if (!strcmp(pvo->name, "filepath")) {
fp = malloc(sizeof(*fp));
fp->next = NULL;
@ -160,7 +166,11 @@ callback_lws_server_status(struct lws *wsi, enum lws_callback_reasons reason,
pvo = pvo->next;
}
v->context = lws_get_context(wsi);
v->vhost = lws_get_vhost(wsi);
v->protocol = lws_get_protocol(wsi);
/* get the initial data */
update(v);
break;
case LWS_CALLBACK_PROTOCOL_DESTROY: /* per vhost */
@ -181,12 +191,6 @@ callback_lws_server_status(struct lws *wsi, enum lws_callback_reasons reason,
return -1;
break;
case LWS_CALLBACK_TIMER:
lws_set_timer_usecs(wsi, v->period_us);
update(v);
lws_callback_on_writable(wsi);
break;
default:
break;
}
@ -198,7 +202,7 @@ static const struct lws_protocols protocols[] = {
{
"lws-server-status",
callback_lws_server_status,
sizeof(struct per_session_data__server_status),
sizeof(struct pss),
1024,
},
};

View file

@ -27,6 +27,13 @@ span.n {
text-align:center;
color:#808020;
}
span.sn {
font-size:12pt;
font-family: Arial;
font-weight:bold;
text-align:center;
color:#808020;
}
span.v {
font-size:12pt;
font-family: Arial;
@ -187,4 +194,4 @@ span.f12 { font-size:12pt }
background:#e0e0c0;
padding:3px;
-webkit-border-radius:3px;
border-radius:3px; }
border-radius:3px; }

View file

@ -17,14 +17,14 @@ function humanize(s)
{
var i = parseInt(s, 10);
if (i > 1000000000)
return (i / 1000000000).toFixed(3) + "G";
if (i >= (1024 * 1024 * 1024))
return (i / (1024 * 1024 * 1024)).toFixed(3) + "Gi";
if (i > 1000000)
return (i / 1000000).toFixed(3) + "M";
if (i >= (1024 * 1024))
return (i / (1024 * 1024)).toFixed(3) + "Mi";
if (i > 1000)
return (i / 1000).toFixed(3) + "K";
if (i > 1024)
return (i / 1024).toFixed(3) + "Ki";
return s;
}
@ -85,20 +85,26 @@ function ws_open_server_status()
s = "<table><tr><td></td><td class=\"dc0\">";
s +=
"Server</td><td>" +
"<span class=n>Version:</span> <span class=v>" +
"<span class=\"sn\">Server Version:</span> <span class=\"v\">" +
san(jso.i.version) + "</span><br>" +
"<span class=n>Uptime:</span> <span class=v>" +
"<span class=\"sn\">Host Uptime:</span> <span class=\"v\">" +
((u / (24 * 3600)) | 0) + "d " +
(((u % (24 * 3600)) / 3600) | 0) + "h " +
(((u % 3600) / 60) | 0) + "m</span>";
if (jso.i.l1)
s = s + ", <span class=n>Load:</span> <span class=v>" + san(jso.i.l1) + " ";
s = s + ", <span class=\"sn\">Host Load:</span> <span class=\"v\">" + san(jso.i.l1) + " ";
if (jso.i.l2)
s = s + san(jso.i.l2) + " ";
if (jso.i.l3)
s = s + san(jso.i.l3);
if (jso.i.l1)
s =s + "<span>";
s =s + "</span>";
if (jso.i.statm) {
var sm = jso.i.statm.split(" ");
s += ", <span class=\"sn\">Virt stack + heap Usage:</span> <span class=\"v\">" +
humanize(parseInt(sm[0], 10) * 4096) + "B</span>";
}
for (n = 0; n < jso.files.length; n++) {
s += "<br><span class=n>" + san(jso.files[n].path) + ":</span><br> " + san(jso.files[n].val);
@ -115,7 +121,7 @@ function ws_open_server_status()
"Deprecated Context " + ci + "</td><td>";
u = parseInt(san(jso.i.contexts[ci].context_uptime), 10);
s += "<span class=n>Uptime:</span> <span class=v>" +
s += "<span class=n>Server Uptime:</span> <span class=v>" +
((u / (24 * 3600)) | 0) + "d " +
(((u % (24 * 3600)) / 3600) | 0) + "h " +
(((u % 3600) / 60) | 0) + "m</span>";
@ -125,8 +131,8 @@ function ws_open_server_status()
"<span class=n>Listening wsi:</span> <span class=v>" + san(jso.i.contexts[ci].listen_wsi) + "</span>, " +
"<span class=n>Current wsi alive:</span> <span class=v>" + (parseInt(san(jso.i.contexts[ci].wsi_alive), 10) -
parseInt(san(jso.i.contexts[ci].listen_wsi), 10)) + "</span><br>" +
"<span class=n>Total Rx:</span> <span class=v>" + humanize(san(jso.i.contexts[ci].rx)) +"</span>, " +
"<span class=n>Total Tx:</span> <span class=v>" + humanize(san(jso.i.contexts[ci].tx)) +"</span><br>" +
"<span class=n>Total Rx:</span> <span class=v>" + humanize(san(jso.i.contexts[ci].rx)) +"B</span>, " +
"<span class=n>Total Tx:</span> <span class=v>" + humanize(san(jso.i.contexts[ci].tx)) +"B</span><br>" +
"<span class=n>CONNECTIONS: HTTP/1.x:</span> <span class=v>" + san(jso.i.contexts[ci].h1_conn) +"</span>, " +
"<span class=n>Websocket:</span> <span class=v>" + san(jso.i.contexts[ci].ws_upg) +"</span>, " +
@ -174,8 +180,8 @@ function ws_open_server_status()
s = s + " (STS)";
s = s +"<br>" +
"<span class=n>Total Rx:</span> <span class=v>" + humanize(san(jso.i.contexts[ci].vhosts[n].rx)) +"</span>, " +
"<span class=n>Total Tx:</span> <span class=v>" + humanize(san(jso.i.contexts[ci].vhosts[n].tx)) +"</span><br>" +
"<span class=n>Total Rx:</span> <span class=v>" + humanize(san(jso.i.contexts[ci].vhosts[n].rx)) +"B</span>, " +
"<span class=n>Total Tx:</span> <span class=v>" + humanize(san(jso.i.contexts[ci].vhosts[n].tx)) +"B</span><br>" +
"<span class=n>CONNECTIONS: HTTP/1.x:</span> <span class=v>" + san(jso.i.contexts[ci].vhosts[n].h1_conn) +"</span>, " +
"<span class=n>Websocket:</span> <span class=v>" + san(jso.i.contexts[ci].vhosts[n].ws_upg) +"</span>, " +
@ -185,29 +191,31 @@ function ws_open_server_status()
"<span class=n>TRANSACTIONS: HTTP/1.x:</span> <span class=v>" + san(jso.i.contexts[ci].vhosts[n].h1_trans) + "</span>, " +
"<span class=n>H2:</span> <span class=v>" + san(jso.i.contexts[ci].vhosts[n].h2_trans) +"</span>, " +
"<span class=n>Total H2 substreams:</span> <span class=v>" + san(jso.i.contexts[ci].vhosts[n].h2_subs) +"</span><br>" +
"<span class=n>Total H2 substreams:</span> <span class=v>" + san(jso.i.contexts[ci].vhosts[n].h2_subs) +"</span><br>";
"<table style=\"margin-left:16px\"><tr><td class=t>Mountpoint</td><td class=t>Origin</td><td class=t>Cache Policy</td></tr>";
var m;
for (m = 0; m < jso.i.contexts[ci].vhosts[n].mounts.length; m++) {
s = s + "<tr><td>";
s = s + "<span class=\"m1\">" + san(jso.i.contexts[ci].vhosts[n].mounts[m].mountpoint) +
"</span></td><td><span class=\"m2\">" +
san(jso.i.contexts[ci].vhosts[n].mounts[m].origin) +
"</span></td><td>";
if (parseInt(san(jso.i.contexts[ci].vhosts[n].mounts[m].cache_max_age), 10))
s = s + "<span class=n>max-age:</span> <span class=v>" +
san(jso.i.contexts[ci].vhosts[n].mounts[m].cache_max_age) +
"</span>, <span class=n>reuse:</span> <span class=v>" +
san(jso.i.contexts[ci].vhosts[n].mounts[m].cache_reuse) +
"</span>, <span class=n>reval:</span> <span class=v>" +
san(jso.i.contexts[ci].vhosts[n].mounts[m].cache_revalidate) +
"</span>, <span class=n>inter:</span> <span class=v>" +
san(jso.i.contexts[ci].vhosts[n].mounts[m].cache_intermediaries);
s = s + "</span></td></tr>";
if (jso.i.contexts[ci].vhosts[n].mounts) {
s = s + "<table><tr><td class=t>Mountpoint</td><td class=t>Origin</td><td class=t>Cache Policy</td></tr>";
var m;
for (m = 0; m < jso.i.contexts[ci].vhosts[n].mounts.length; m++) {
s = s + "<tr><td>";
s = s + "<span class=\"m1\">" + san(jso.i.contexts[ci].vhosts[n].mounts[m].mountpoint) +
"</span></td><td><span class=\"m2\">" +
san(jso.i.contexts[ci].vhosts[n].mounts[m].origin) +
"</span></td><td>";
if (parseInt(san(jso.i.contexts[ci].vhosts[n].mounts[m].cache_max_age), 10))
s = s + "<span class=n>max-age:</span> <span class=v>" +
san(jso.i.contexts[ci].vhosts[n].mounts[m].cache_max_age) +
"</span>, <span class=n>reuse:</span> <span class=v>" +
san(jso.i.contexts[ci].vhosts[n].mounts[m].cache_reuse) +
"</span>, <span class=n>reval:</span> <span class=v>" +
san(jso.i.contexts[ci].vhosts[n].mounts[m].cache_revalidate) +
"</span>, <span class=n>inter:</span> <span class=v>" +
san(jso.i.contexts[ci].vhosts[n].mounts[m].cache_intermediaries);
s = s + "</span></td></tr>";
}
s = s + "</table>";
}
s = s + "</table>";
s = s + "</td></tr>";
}