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:
parent
f74326e6e1
commit
fb90b04e97
4 changed files with 123 additions and 88 deletions
|
@ -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, "{ "
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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>";
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue