You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
277 lines
6.5 KiB
277 lines
6.5 KiB
7 months ago
|
/*
|
||
|
* libwebsockets - small server side websockets and web server implementation
|
||
|
*
|
||
|
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
|
||
|
*
|
||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
|
* of this software and associated documentation files (the "Software"), to
|
||
|
* deal in the Software without restriction, including without limitation the
|
||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||
|
* furnished to do so, subject to the following conditions:
|
||
|
*
|
||
|
* The above copyright notice and this permission notice shall be included in
|
||
|
* all copies or substantial portions of the Software.
|
||
|
*
|
||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||
|
* IN THE SOFTWARE.
|
||
|
*/
|
||
|
|
||
|
#include "private-lib-core.h"
|
||
|
|
||
|
#if defined(LWS_WITH_STATS)
|
||
|
|
||
|
uint64_t
|
||
|
lws_stats_get(struct lws_context *context, int index)
|
||
|
{
|
||
|
struct lws_context_per_thread *pt = &context->pt[0];
|
||
|
|
||
|
if (index >= LWSSTATS_SIZE)
|
||
|
return 0;
|
||
|
|
||
|
return pt->lws_stats[index];
|
||
|
}
|
||
|
|
||
|
static const char * stat_names[] = {
|
||
|
"C_CONNECTIONS",
|
||
|
"C_API_CLOSE",
|
||
|
"C_API_READ",
|
||
|
"C_API_LWS_WRITE",
|
||
|
"C_API_WRITE",
|
||
|
"C_WRITE_PARTIALS",
|
||
|
"C_WRITEABLE_CB_REQ",
|
||
|
"C_WRITEABLE_CB_EFF_REQ",
|
||
|
"C_WRITEABLE_CB",
|
||
|
"C_SSL_CONNECTIONS_FAILED",
|
||
|
"C_SSL_CONNECTIONS_ACCEPTED",
|
||
|
"C_SSL_CONNECTIONS_ACCEPT_SPIN",
|
||
|
"C_SSL_CONNS_HAD_RX",
|
||
|
"C_TIMEOUTS",
|
||
|
"C_SERVICE_ENTRY",
|
||
|
"B_READ",
|
||
|
"B_WRITE",
|
||
|
"B_PARTIALS_ACCEPTED_PARTS",
|
||
|
"US_SSL_ACCEPT_LATENCY_AVG",
|
||
|
"US_WRITABLE_DELAY_AVG",
|
||
|
"US_WORST_WRITABLE_DELAY",
|
||
|
"US_SSL_RX_DELAY_AVG",
|
||
|
"C_PEER_LIMIT_AH_DENIED",
|
||
|
"C_PEER_LIMIT_WSI_DENIED",
|
||
|
"C_CONNECTIONS_CLIENT",
|
||
|
"C_CONNECTIONS_CLIENT_FAILED",
|
||
|
};
|
||
|
|
||
|
static int
|
||
|
quantify(struct lws_context *context, int tsi, char *p, int len, int idx,
|
||
|
uint64_t *sum)
|
||
|
{
|
||
|
const lws_humanize_unit_t *schema = humanize_schema_si;
|
||
|
struct lws_context_per_thread *pt = &context->pt[tsi];
|
||
|
uint64_t u, u1;
|
||
|
|
||
|
lws_pt_stats_lock(pt);
|
||
|
u = pt->lws_stats[idx];
|
||
|
|
||
|
/* it's supposed to be an average? */
|
||
|
|
||
|
switch (idx) {
|
||
|
case LWSSTATS_US_SSL_ACCEPT_LATENCY_AVG:
|
||
|
u1 = pt->lws_stats[LWSSTATS_C_SSL_CONNECTIONS_ACCEPTED];
|
||
|
if (u1)
|
||
|
u = u / u1;
|
||
|
break;
|
||
|
case LWSSTATS_US_SSL_RX_DELAY_AVG:
|
||
|
u1 = pt->lws_stats[LWSSTATS_C_SSL_CONNS_HAD_RX];
|
||
|
if (u1)
|
||
|
u = u / u1;
|
||
|
break;
|
||
|
case LWSSTATS_US_WRITABLE_DELAY_AVG:
|
||
|
u1 = pt->lws_stats[LWSSTATS_C_WRITEABLE_CB];
|
||
|
if (u1)
|
||
|
u = u / u1;
|
||
|
break;
|
||
|
}
|
||
|
lws_pt_stats_unlock(pt);
|
||
|
|
||
|
*sum += u;
|
||
|
|
||
|
switch (stat_names[idx][0]) {
|
||
|
case 'U':
|
||
|
schema = humanize_schema_us;
|
||
|
break;
|
||
|
case 'B':
|
||
|
schema = humanize_schema_si_bytes;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return lws_humanize(p, len, u, schema);
|
||
|
}
|
||
|
|
||
|
|
||
|
void
|
||
|
lws_stats_log_dump(struct lws_context *context)
|
||
|
{
|
||
|
struct lws_vhost *v = context->vhost_list;
|
||
|
uint64_t summary[LWSSTATS_SIZE];
|
||
|
char bufline[128], *p, *end = bufline + sizeof(bufline) - 1;
|
||
|
int n, m;
|
||
|
|
||
|
if (!context->updated)
|
||
|
return;
|
||
|
|
||
|
context->updated = 0;
|
||
|
memset(summary, 0, sizeof(summary));
|
||
|
|
||
|
lwsl_notice("\n");
|
||
|
lwsl_notice("LWS internal statistics dump ----->\n");
|
||
|
for (n = 0; n < (int)LWS_ARRAY_SIZE(stat_names); n++) {
|
||
|
uint64_t u = 0;
|
||
|
|
||
|
/* if it's all zeroes, don't report it */
|
||
|
|
||
|
for (m = 0; m < context->count_threads; m++) {
|
||
|
struct lws_context_per_thread *pt = &context->pt[m];
|
||
|
|
||
|
u |= pt->lws_stats[n];
|
||
|
}
|
||
|
if (!u)
|
||
|
continue;
|
||
|
|
||
|
p = bufline;
|
||
|
p += lws_snprintf(p, lws_ptr_diff(end, p), "%28s: ",
|
||
|
stat_names[n]);
|
||
|
|
||
|
for (m = 0; m < context->count_threads; m++)
|
||
|
quantify(context, m, p, lws_ptr_diff(end, p), n, &summary[n]);
|
||
|
|
||
|
lwsl_notice("%s\n", bufline);
|
||
|
}
|
||
|
|
||
|
lwsl_notice("Simultaneous SSL restriction: %8d/%d\n",
|
||
|
context->simultaneous_ssl,
|
||
|
context->simultaneous_ssl_restriction);
|
||
|
|
||
|
lwsl_notice("Live wsi: %8d\n",
|
||
|
context->count_wsi_allocated);
|
||
|
|
||
|
while (v) {
|
||
|
if (v->lserv_wsi &&
|
||
|
v->lserv_wsi->position_in_fds_table != LWS_NO_FDS_POS) {
|
||
|
|
||
|
struct lws_context_per_thread *pt =
|
||
|
&context->pt[(int)v->lserv_wsi->tsi];
|
||
|
struct lws_pollfd *pfd;
|
||
|
|
||
|
pfd = &pt->fds[v->lserv_wsi->position_in_fds_table];
|
||
|
|
||
|
lwsl_notice(" Listen port %d actual POLLIN: %d\n",
|
||
|
v->listen_port,
|
||
|
(int)pfd->events & LWS_POLLIN);
|
||
|
}
|
||
|
|
||
|
v = v->vhost_next;
|
||
|
}
|
||
|
|
||
|
for (n = 0; n < context->count_threads; n++) {
|
||
|
struct lws_context_per_thread *pt = &context->pt[n];
|
||
|
struct lws *wl;
|
||
|
int m = 0;
|
||
|
|
||
|
lwsl_notice("PT %d\n", n + 1);
|
||
|
|
||
|
lws_pt_lock(pt, __func__);
|
||
|
|
||
|
lwsl_notice(" AH in use / max: %d / %d\n",
|
||
|
pt->http.ah_count_in_use,
|
||
|
context->max_http_header_pool);
|
||
|
|
||
|
wl = pt->http.ah_wait_list;
|
||
|
while (wl) {
|
||
|
m++;
|
||
|
wl = wl->http.ah_wait_list;
|
||
|
}
|
||
|
|
||
|
lwsl_notice(" AH wait list count / actual: %d / %d\n",
|
||
|
pt->http.ah_wait_list_length, m);
|
||
|
|
||
|
lws_pt_unlock(pt);
|
||
|
}
|
||
|
|
||
|
#if defined(LWS_WITH_PEER_LIMITS)
|
||
|
m = 0;
|
||
|
for (n = 0; n < (int)context->pl_hash_elements; n++) {
|
||
|
lws_start_foreach_llp(struct lws_peer **, peer,
|
||
|
context->pl_hash_table[n]) {
|
||
|
m++;
|
||
|
} lws_end_foreach_llp(peer, next);
|
||
|
}
|
||
|
|
||
|
lwsl_notice(" Peers: total active %d\n", m);
|
||
|
if (m > 10) {
|
||
|
m = 10;
|
||
|
lwsl_notice(" (showing 10 peers only)\n");
|
||
|
}
|
||
|
|
||
|
if (m) {
|
||
|
for (n = 0; n < (int)context->pl_hash_elements; n++) {
|
||
|
char buf[72];
|
||
|
|
||
|
lws_start_foreach_llp(struct lws_peer **, peer,
|
||
|
context->pl_hash_table[n]) {
|
||
|
struct lws_peer *df = *peer;
|
||
|
|
||
|
if (!lws_plat_inet_ntop(df->af, df->addr, buf,
|
||
|
sizeof(buf) - 1))
|
||
|
strcpy(buf, "unknown");
|
||
|
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
|
||
|
lwsl_notice(" peer %s: count wsi: %d, count ah: %d\n",
|
||
|
buf, df->count_wsi,
|
||
|
df->http.count_ah);
|
||
|
#else
|
||
|
lwsl_notice(" peer %s: count wsi: %d\n",
|
||
|
buf, df->count_wsi);
|
||
|
#endif
|
||
|
|
||
|
if (!--m)
|
||
|
break;
|
||
|
} lws_end_foreach_llp(peer, next);
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
lwsl_notice("\n");
|
||
|
}
|
||
|
|
||
|
void
|
||
|
lws_stats_bump(struct lws_context_per_thread *pt, int i, uint64_t bump)
|
||
|
{
|
||
|
lws_pt_stats_lock(pt);
|
||
|
pt->lws_stats[i] += bump;
|
||
|
if (i != LWSSTATS_C_SERVICE_ENTRY) {
|
||
|
pt->updated = 1;
|
||
|
pt->context->updated = 1;
|
||
|
}
|
||
|
lws_pt_stats_unlock(pt);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
lws_stats_max(struct lws_context_per_thread *pt, int index, uint64_t val)
|
||
|
{
|
||
|
lws_pt_stats_lock(pt);
|
||
|
if (val > pt->lws_stats[index]) {
|
||
|
pt->lws_stats[index] = val;
|
||
|
pt->updated = 1;
|
||
|
pt->context->updated = 1;
|
||
|
}
|
||
|
lws_pt_stats_unlock(pt);
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
|