| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276 |
- /*
- * libwebsockets - small server side websockets and web server implementation
- *
- * Copyright (C) 2010 - 2019 Andy Green <[email protected]>
- *
- * 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
|