LWS_WITH_STATS
authorAndy Green <andy@warmcat.com>
Sun, 7 May 2017 02:02:03 +0000 (10:02 +0800)
committerAndy Green <andy@warmcat.com>
Tue, 9 May 2017 06:19:43 +0000 (14:19 +0800)
14 files changed:
CMakeLists.txt
component.mk
lib/context.c
lib/libwebsockets.c
lib/libwebsockets.h
lib/lws-plat-esp32.c
lib/lws-plat-unix.c
lib/output.c
lib/pollfd.c
lib/private-libwebsockets.h
lib/server.c
lib/service.c
lib/ssl.c
lws_config.h.in

index a962682..b035f8d 100644 (file)
@@ -117,6 +117,7 @@ option(LWS_WITH_RANGES "Support http ranges (RFC7233)" ON)
 option(LWS_FALLBACK_GETHOSTBYNAME "Also try to do dns resolution using gethostbyname if getaddrinfo fails" OFF)
 option(LWS_WITH_ZIP_FOPS "Support serving pre-zipped files" ON)
 option(LWS_AVOID_SIGPIPE_IGN "Android 7+ seems to need this" OFF)
+option(LWS_WITH_STATS "Keep statistics of lws internal operations" OFF)
 
 if (LWS_WITH_LWSWS)
  message(STATUS "LWS_WITH_LWSWS --> Enabling LWS_WITH_PLUGINS and LWS_WITH_LIBUV")
@@ -1767,6 +1768,7 @@ message(" LWS_PLAT_OPTEE = ${LWS_PLAT_OPTEE}")
 message(" LWS_WITH_ESP32 = ${LWS_WITH_ESP32}")
 message(" LWS_WITH_ZIP_FOPS = ${LWS_WITH_ZIP_FOPS}")
 message(" LWS_AVOID_SIGPIPE_IGN = ${LWS_AVOID_SIGPIPE_IGN}")
+message(" LWS_WITH_STATS = ${LWS_WITH_STATS}")
 
 message("---------------------------------------------------------------------")
 
index f7dbbd8..ed334a8 100644 (file)
@@ -25,6 +25,7 @@ build:
                -DCMAKE_BUILD_TYPE=RELEASE \
                -DOPENSSL_INCLUDE_DIR=${IDF_PATH}/components/openssl/include \
                -DOPENSSL_LIBRARIES=x \
+               -DLWS_WITH_STATS=1 \
                -DZLIB_LIBRARY=$(BUILD_DIR_BASE)/zlib/libzlib.a \
                -DZLIB_INCLUDE_DIR=$(COMPONENT_PATH)/../zlib \
                -DLWS_WITH_ESP32=1 ;\
index 435f48e..f791ca6 100644 (file)
@@ -616,6 +616,9 @@ lws_create_context(struct lws_context_creation_info *info)
        lwsl_info(" LWS_MAX_SMP           : %u\n", LWS_MAX_SMP);
        lwsl_info(" SPEC_LATEST_SUPPORTED : %u\n", SPEC_LATEST_SUPPORTED);
        lwsl_info(" sizeof (*info)        : %ld\n", (long)sizeof(*info));
+#if defined(LWS_WITH_STATS)
+       lwsl_notice(" LWS_WITH_STATS        : on\n");
+#endif
 #if LWS_POSIX
        lwsl_info(" SYSTEM_RANDOM_FILEPATH: '%s'\n", SYSTEM_RANDOM_FILEPATH);
 #endif
@@ -1109,12 +1112,13 @@ lws_context_destroy2(struct lws_context *context)
                vh = vh1;
        }
 
+       lws_stats_log_dump(context);
+
        lws_ssl_context_destroy(context);
        lws_plat_context_late_destroy(context);
 
        if (context->external_baggage_free_on_destroy)
                free(context->external_baggage_free_on_destroy);
 
-
        lws_free(context);
 }
index 98b8df9..7750429 100755 (executable)
@@ -249,6 +249,7 @@ lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason)
 
        context = wsi->context;
        pt = &context->pt[(int)wsi->tsi];
+       lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_C_API_CLOSE, 1);
 
        /* if we have children, close them first */
        if (wsi->child_list) {
@@ -3110,3 +3111,81 @@ lws_json_dump_context(const struct lws_context *context, char *buf, int len,
 }
 
 #endif
+
+#if defined(LWS_WITH_STATS)
+
+LWS_VISIBLE LWS_EXTERN uint64_t
+lws_stats_get(struct lws_context *context, int index)
+{
+       if (index >= LWSSTATS_SIZE)
+               return 0;
+
+       return context->lws_stats[index];
+}
+
+LWS_VISIBLE LWS_EXTERN void
+lws_stats_log_dump(struct lws_context *context)
+{
+       if (!context->updated)
+               return;
+
+       context->updated = 0;
+
+       lwsl_notice("\n");
+       lwsl_notice("LWS internal statistics dump ----->\n");
+       lwsl_notice("LWSSTATS_C_CONNECTIONS:                     %8llu\n", (unsigned long long)lws_stats_get(context, LWSSTATS_C_CONNECTIONS));
+       lwsl_notice("LWSSTATS_C_API_CLOSE:                       %8llu\n", (unsigned long long)lws_stats_get(context, LWSSTATS_C_API_CLOSE));
+       lwsl_notice("LWSSTATS_C_API_READ:                        %8llu\n", (unsigned long long)lws_stats_get(context, LWSSTATS_C_API_READ));
+       lwsl_notice("LWSSTATS_C_API_LWS_WRITE:                   %8llu\n", (unsigned long long)lws_stats_get(context, LWSSTATS_C_API_LWS_WRITE));
+       lwsl_notice("LWSSTATS_C_API_WRITE:                       %8llu\n", (unsigned long long)lws_stats_get(context, LWSSTATS_C_API_WRITE));
+       lwsl_notice("LWSSTATS_C_WRITE_PARTIALS:                  %8llu\n", (unsigned long long)lws_stats_get(context, LWSSTATS_C_WRITE_PARTIALS));
+       lwsl_notice("LWSSTATS_C_WRITEABLE_CB_REQ:                %8llu\n", (unsigned long long)lws_stats_get(context, LWSSTATS_C_WRITEABLE_CB_REQ));
+       lwsl_notice("LWSSTATS_C_WRITEABLE_CB_EFF_REQ:            %8llu\n", (unsigned long long)lws_stats_get(context, LWSSTATS_C_WRITEABLE_CB_EFF_REQ));
+       lwsl_notice("LWSSTATS_C_WRITEABLE_CB:                    %8llu\n", (unsigned long long)lws_stats_get(context, LWSSTATS_C_WRITEABLE_CB));
+       lwsl_notice("LWSSTATS_C_SSL_CONNECTIONS_FAILED:          %8llu\n", (unsigned long long)lws_stats_get(context, LWSSTATS_C_SSL_CONNECTIONS_FAILED));
+       lwsl_notice("LWSSTATS_C_SSL_CONNECTIONS_ACCEPTED:        %8llu\n", (unsigned long long)lws_stats_get(context, LWSSTATS_C_SSL_CONNECTIONS_ACCEPTED));
+       lwsl_notice("LWSSTATS_C_TIMEOUTS:                        %8llu\n", (unsigned long long)lws_stats_get(context, LWSSTATS_C_TIMEOUTS));
+       lwsl_notice("LWSSTATS_C_SERVICE_ENTRY:                   %8llu\n", (unsigned long long)lws_stats_get(context, LWSSTATS_C_SERVICE_ENTRY));
+       lwsl_notice("LWSSTATS_B_READ:                            %8llu\n", (unsigned long long)lws_stats_get(context, LWSSTATS_B_READ));
+       lwsl_notice("LWSSTATS_B_WRITE:                           %8llu\n", (unsigned long long)lws_stats_get(context, LWSSTATS_B_WRITE));
+       lwsl_notice("LWSSTATS_B_PARTIALS_ACCEPTED_PARTS:         %8llu\n", (unsigned long long)lws_stats_get(context, LWSSTATS_B_PARTIALS_ACCEPTED_PARTS));
+       lwsl_notice("LWSSTATS_MS_SSL_CONNECTIONS_ACCEPTED_DELAY: %8llums\n", (unsigned long long)lws_stats_get(context, LWSSTATS_MS_SSL_CONNECTIONS_ACCEPTED_DELAY) / 1000);
+       if (lws_stats_get(context, LWSSTATS_C_SSL_CONNECTIONS_ACCEPTED))
+               lwsl_notice("  Avg accept delay:                         %8llums\n",
+                       (unsigned long long)(lws_stats_get(context, LWSSTATS_MS_SSL_CONNECTIONS_ACCEPTED_DELAY) /
+                       lws_stats_get(context, LWSSTATS_C_SSL_CONNECTIONS_ACCEPTED)) / 1000);
+       lwsl_notice("LWSSTATS_MS_WRITABLE_DELAY:                 %8lluus\n",
+                       (unsigned long long)lws_stats_get(context, LWSSTATS_MS_WRITABLE_DELAY));
+       lwsl_notice("LWSSTATS_MS_WORST_WRITABLE_DELAY:           %8lluus\n",
+                               (unsigned long long)lws_stats_get(context, LWSSTATS_MS_WORST_WRITABLE_DELAY));
+       if (lws_stats_get(context, LWSSTATS_C_WRITEABLE_CB))
+               lwsl_notice("  Avg writable delay:                       %8lluus\n",
+                       (unsigned long long)(lws_stats_get(context, LWSSTATS_MS_WRITABLE_DELAY) /
+                       lws_stats_get(context, LWSSTATS_C_WRITEABLE_CB)));
+       lwsl_notice("\n");
+}
+
+void
+lws_stats_atomic_bump(struct lws_context * context,
+               struct lws_context_per_thread *pt, int index, uint64_t bump)
+{
+       lws_pt_lock(pt);
+       context->lws_stats[index] += bump;
+       if (index != LWSSTATS_C_SERVICE_ENTRY)
+               context->updated = 1;
+       lws_pt_unlock(pt);
+}
+
+void
+lws_stats_atomic_max(struct lws_context * context,
+               struct lws_context_per_thread *pt, int index, uint64_t val)
+{
+       lws_pt_lock(pt);
+       if (val > context->lws_stats[index]) {
+               context->lws_stats[index] = val;
+               context->updated = 1;
+       }
+       lws_pt_unlock(pt);
+}
+
+#endif
index 3baaf4e..4065aad 100644 (file)
@@ -4784,6 +4784,54 @@ lws_email_destroy(struct lws_email *email);
 #endif
 //@}
 
+/*
+ * Stats are all uint64_t numbers that start at 0.
+ * Index names here have the convention
+ *
+ *  _C_ counter
+ *  _B_ byte count
+ *  _MS_ millisecond count
+ */
+
+enum {
+       LWSSTATS_C_CONNECTIONS, /**< count incoming connections */
+       LWSSTATS_C_API_CLOSE, /**< count calls to close api */
+       LWSSTATS_C_API_READ, /**< count calls to read from socket api */
+       LWSSTATS_C_API_LWS_WRITE, /**< count calls to lws_write API */
+       LWSSTATS_C_API_WRITE, /**< count calls to write API */
+       LWSSTATS_C_WRITE_PARTIALS, /**< count of partial writes */
+       LWSSTATS_C_WRITEABLE_CB_REQ, /**< count of writable callback requests */
+       LWSSTATS_C_WRITEABLE_CB_EFF_REQ, /**< count of effective writable callback requests */
+       LWSSTATS_C_WRITEABLE_CB, /**< count of writable callbacks */
+       LWSSTATS_C_SSL_CONNECTIONS_FAILED, /**< count of failed SSL connections */
+       LWSSTATS_C_SSL_CONNECTIONS_ACCEPTED, /**< count of accepted SSL connections */
+       LWSSTATS_C_TIMEOUTS, /**< count of timed-out connections */
+       LWSSTATS_C_SERVICE_ENTRY, /**< count of entries to lws service loop */
+       LWSSTATS_B_READ, /**< aggregate bytes read */
+       LWSSTATS_B_WRITE, /**< aggregate bytes written */
+       LWSSTATS_B_PARTIALS_ACCEPTED_PARTS, /**< aggreate of size of accepted write data from new partials */
+       LWSSTATS_MS_SSL_CONNECTIONS_ACCEPTED_DELAY, /**< aggregate delay in accepting connection */
+       LWSSTATS_MS_WRITABLE_DELAY, /**< aggregate delay between asking for writable and getting cb */
+       LWSSTATS_MS_WORST_WRITABLE_DELAY, /**< single worst delay between asking for writable and getting cb */
+
+       /* Add new things just above here ---^
+        * This is part of the ABI, don't needlessly break compatibility */
+       LWSSTATS_SIZE
+};
+
+#if defined(LWS_WITH_STATS)
+
+LWS_VISIBLE LWS_EXTERN uint64_t
+lws_stats_get(struct lws_context *context, int index);
+LWS_VISIBLE LWS_EXTERN void
+lws_stats_log_dump(struct lws_context *context);
+#else
+static inline uint64_t
+lws_stats_get(struct lws_context *context, int index) { return 0; }
+static inline void
+lws_stats_log_dump(struct lws_context *context) { }
+#endif
+
 #ifdef __cplusplus
 }
 #endif
index 19536ce..dc54911 100644 (file)
@@ -115,6 +115,7 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
                return 1;
 
        pt = &context->pt[tsi];
+       lws_stats_atomic_bump(context, pt, LWSSTATS_C_SERVICE_ENTRY, 1);
 
        if (timeout_ms < 0)
                goto faked_service;
index 3c41a46..b9f317b 100644 (file)
@@ -114,6 +114,8 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
 
        pt = &context->pt[tsi];
 
+       lws_stats_atomic_bump(context, pt, LWSSTATS_C_SERVICE_ENTRY, 1);
+
        if (timeout_ms < 0)
                goto faked_service;
 
index a41b0e0..efb2606 100644 (file)
@@ -95,10 +95,13 @@ LWS_VISIBLE void lwsl_hexdump(void *vbuf, size_t len)
 int lws_issue_raw(struct lws *wsi, unsigned char *buf, size_t len)
 {
        struct lws_context *context = lws_get_context(wsi);
+       struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
        size_t real_len = len;
        unsigned int n;
        int m;
 
+       lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_C_API_WRITE, 1);
+
        if (!len)
                return 0;
        /* just ignore sends after we cleared the truncation buffer */
@@ -207,6 +210,9 @@ handle_truncated_send:
        lwsl_debug("%p new partial sent %d from %lu total\n", wsi, n,
                    (unsigned long)real_len);
 
+       lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_C_WRITE_PARTIALS, 1);
+       lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_B_PARTIALS_ACCEPTED_PARTS, n);
+
        /*
         *  - if we still have a suitable malloc lying around, use it
         *  - or, if too small, reallocate it
@@ -244,12 +250,16 @@ LWS_VISIBLE int lws_write(struct lws *wsi, unsigned char *buf, size_t len,
        int pre = 0, n;
        size_t orig_len = len;
 
+       lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_C_API_LWS_WRITE, 1);
+
        if ((int)len < 0) {
                lwsl_err("%s: suspicious len int %d, ulong %lu\n", __func__,
                                (int)len, (unsigned long)len);
                return -1;
        }
 
+       lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_B_WRITE, len);
+
 #ifdef LWS_WITH_ACCESS_LOG
        wsi->access_log.sent += len;
 #endif
@@ -766,12 +776,17 @@ file_had_it:
 LWS_VISIBLE int
 lws_ssl_capable_read_no_ssl(struct lws *wsi, unsigned char *buf, int len)
 {
+       struct lws_context *context = wsi->context;
+       struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
        int n;
 
+       lws_stats_atomic_bump(context, pt, LWSSTATS_C_API_READ, 1);
+
        n = recv(wsi->desc.sockfd, (char *)buf, len, 0);
        if (n >= 0) {
                if (wsi->vhost)
                        wsi->vhost->conn_stats.rx += n;
+               lws_stats_atomic_bump(context, pt, LWSSTATS_B_READ, n);
                lws_restart_ws_ping_pong_timer(wsi);
                return n;
        }
index b43f791..7c3a0ef 100644 (file)
@@ -336,6 +336,7 @@ lws_change_pollfd(struct lws *wsi, int _and, int _or)
 LWS_VISIBLE int
 lws_callback_on_writable(struct lws *wsi)
 {
+       struct lws_context_per_thread *pt;
 #ifdef LWS_USE_HTTP2
        struct lws *network_wsi, *wsi2;
        int already;
@@ -347,6 +348,15 @@ lws_callback_on_writable(struct lws *wsi)
        if (wsi->socket_is_permanently_unusable)
                return 0;
 
+       pt = &wsi->context->pt[(int)wsi->tsi];
+       lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_C_WRITEABLE_CB_REQ, 1);
+#if defined(LWS_WITH_STATS)
+       if (!wsi->active_writable_req_us) {
+               wsi->active_writable_req_us = time_in_microseconds();
+               lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_C_WRITEABLE_CB_EFF_REQ, 1);
+       }
+#endif
+
 #ifdef LWS_USE_HTTP2
        lwsl_info("%s: %p\n", __func__, wsi);
 
index d59bd7b..21fccdc 100644 (file)
@@ -879,6 +879,12 @@ struct lws_context {
        char worst_latency_info[256];
 #endif
 
+#if defined(LWS_WITH_STATS)
+       uint64_t lws_stats[LWSSTATS_SIZE];
+       uint64_t last_dump;
+       int updated;
+#endif
+
        int max_fds;
 #if defined(LWS_USE_LIBEV) || defined(LWS_USE_LIBUV) || defined(LWS_USE_LIBEVENT)
        int use_ev_sigint;
@@ -1465,6 +1471,9 @@ struct lws {
        SSL *ssl;
        BIO *client_bio;
        struct lws *pending_read_list_prev, *pending_read_list_next;
+#if defined(LWS_WITH_STATS)
+       uint64_t accept_start_us;
+#endif
 #endif
 #ifdef LWS_WITH_HTTP_PROXY
        struct lws_rewrite *rw;
@@ -1474,7 +1483,9 @@ struct lws {
        unsigned long latency_start;
 #endif
        lws_sock_file_fd_type desc; /* .filefd / .sockfd */
-
+#if defined(LWS_WITH_STATS)
+       uint64_t active_writable_req_us;
+#endif
        /* ints */
        int position_in_fds_table;
        int rxflow_len;
@@ -2072,6 +2083,22 @@ lws_same_vh_protocol_remove(struct lws *wsi);
 LWS_EXTERN void
 lws_same_vh_protocol_insert(struct lws *wsi, int n);
 
+#if defined(LWS_WITH_STATS)
+void
+lws_stats_atomic_bump(struct lws_context * context,
+               struct lws_context_per_thread *pt, int index, uint64_t bump);
+void
+lws_stats_atomic_max(struct lws_context * context,
+               struct lws_context_per_thread *pt, int index, uint64_t val);
+#else
+static inline uint64_t lws_stats_atomic_bump(struct lws_context * context,
+               struct lws_context_per_thread *pt, int index, uint64_t bump) {
+       (void)context; (void)pt; (void)index; (void)bump; return 0; }
+static inline uint64_t lws_stats_atomic_max(struct lws_context * context,
+               struct lws_context_per_thread *pt, int index, uint64_t val) {
+       (void)context; (void)pt; (void)index; (void)val; return 0; }
+#endif
+
 #ifdef __cplusplus
 };
 #endif
index d1ff1e9..f442b94 100644 (file)
@@ -1757,6 +1757,7 @@ lws_adopt_descriptor_vhost(struct lws_vhost *vh, lws_adoption_type type,
 {
        struct lws_context *context = vh->context;
        struct lws *new_wsi = lws_create_new_server_wsi(vh);
+       struct lws_context_per_thread *pt;
        int n, ssl = 0;
 
        if (!new_wsi) {
@@ -1764,6 +1765,8 @@ lws_adopt_descriptor_vhost(struct lws_vhost *vh, lws_adoption_type type,
                        compatible_close(fd.sockfd);
                return NULL;
        }
+       pt = &context->pt[(int)new_wsi->tsi];
+       lws_stats_atomic_bump(context, pt, LWSSTATS_C_CONNECTIONS, 1);
 
        if (parent) {
                new_wsi->parent = parent;
@@ -2192,6 +2195,16 @@ try_pollout:
                }
 
                if (wsi->mode == LWSCM_RAW) {
+                       lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_C_WRITEABLE_CB, 1);
+#if defined(LWS_WITH_STATS)
+                       {
+                               uint64_t ul = time_in_microseconds() - wsi->active_writable_req_us;
+
+                               lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_MS_WRITABLE_DELAY, ul);
+                               lws_stats_atomic_max(wsi->context, pt, LWSSTATS_MS_WORST_WRITABLE_DELAY, ul);
+                               wsi->active_writable_req_us = 0;
+                       }
+#endif
                        n = user_callback_handle_rxflow(wsi->protocol->callback,
                                        wsi, LWS_CALLBACK_RAW_WRITEABLE,
                                        wsi->user_space, NULL, 0);
@@ -2206,6 +2219,18 @@ try_pollout:
                        break;
 
                if (wsi->state != LWSS_HTTP_ISSUING_FILE) {
+
+                       lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_C_WRITEABLE_CB, 1);
+#if defined(LWS_WITH_STATS)
+                       {
+                               uint64_t ul = time_in_microseconds() - wsi->active_writable_req_us;
+
+                               lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_MS_WRITABLE_DELAY, ul);
+                               lws_stats_atomic_max(wsi->context, pt, LWSSTATS_MS_WORST_WRITABLE_DELAY, ul);
+                               wsi->active_writable_req_us = 0;
+                       }
+#endif
+
                        n = user_callback_handle_rxflow(wsi->protocol->callback,
                                        wsi, LWS_CALLBACK_HTTP_WRITEABLE,
                                        wsi->user_space, NULL, 0);
index b23defd..e33c6a7 100644 (file)
 static int
 lws_calllback_as_writeable(struct lws *wsi)
 {
+       struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
        int n;
 
+       lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_C_WRITEABLE_CB, 1);
+#if defined(LWS_WITH_STATS)
+       {
+               uint64_t ul = time_in_microseconds() - wsi->active_writable_req_us;
+
+               lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_MS_WRITABLE_DELAY, ul);
+               lws_stats_atomic_max(wsi->context, pt, LWSSTATS_MS_WORST_WRITABLE_DELAY, ul);
+               wsi->active_writable_req_us = 0;
+       }
+#endif
+
        switch (wsi->mode) {
        case LWSCM_RAW:
                n = LWS_CALLBACK_RAW_WRITEABLE;
@@ -425,6 +437,8 @@ lws_service_timeout_check(struct lws *wsi, unsigned int sec)
                if (wsi->desc.sockfd != LWS_SOCK_INVALID && wsi->position_in_fds_table >= 0)
                        n = pt->fds[wsi->position_in_fds_table].events;
 
+               lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_C_TIMEOUTS, 1);
+
                /* no need to log normal idle keepalive timeout */
                if (wsi->pending_timeout != PENDING_TIMEOUT_HTTP_KEEPALIVE_IDLE)
                        lwsl_notice("wsi %p: TIMEDOUT WAITING on %d (did hdr %d, ah %p, wl %d, pfd events %d) %llu vs %llu\n",
@@ -786,6 +800,13 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, int t
        if (context->last_timeout_check_s != now) {
                context->last_timeout_check_s = now;
 
+#if defined(LWS_WITH_STATS)
+               if (!tsi && now - context->last_dump > 10) {
+                       lws_stats_log_dump(context);
+                       context->last_dump = now;
+               }
+#endif
+
                lws_plat_service_periodic(context);
 
                /* retire unused deprecated context */
index a7969f3..b5f9e1e 100644 (file)
--- a/lib/ssl.c
+++ b/lib/ssl.c
@@ -298,6 +298,8 @@ lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, int len)
        if (!wsi->ssl)
                return lws_ssl_capable_read_no_ssl(wsi, buf, len);
 
+       lws_stats_atomic_bump(context, pt, LWSSTATS_C_API_READ, 1);
+
        errno = 0;
        n = SSL_read(wsi->ssl, buf, len);
 #if defined(LWS_WITH_ESP32)
@@ -354,6 +356,8 @@ lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, int len)
                return LWS_SSL_CAPABLE_ERROR;
        }
 
+       lws_stats_atomic_bump(context, pt, LWSSTATS_B_READ, n);
+
        if (wsi->vhost)
                wsi->vhost->conn_stats.rx += n;
 
@@ -652,6 +656,11 @@ lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd)
 
                /* normal SSL connection processing path */
 
+#if defined(LWS_WITH_STATS)
+               if (!wsi->accept_start_us)
+                       wsi->accept_start_us = time_in_microseconds();
+#endif
+
                n = SSL_accept(wsi->ssl);
                lws_latency(context, wsi,
                        "SSL_accept LWSCM_SSL_ACK_PENDING\n", n, n == 1);
@@ -686,13 +695,18 @@ go_again:
 
                        break;
                }
-
+               lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_C_SSL_CONNECTIONS_FAILED, 1);
                 lwsl_err("SSL_accept failed socket %u: %s\n", wsi->desc.sockfd,
                          lws_ssl_get_error_string(m, n, buf, sizeof(buf)));
                lws_ssl_elaborate_error();
                goto fail;
 
 accepted:
+               lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_C_SSL_CONNECTIONS_ACCEPTED, 1);
+#if defined(LWS_WITH_STATS)
+               lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_MS_SSL_CONNECTIONS_ACCEPTED_DELAY, time_in_microseconds() - wsi->accept_start_us);
+#endif
+
                /* OK, we are accepted... give him some time to negotiate */
                lws_set_timeout(wsi, PENDING_TIMEOUT_ESTABLISH_WITH_SERVER,
                                context->timeout_secs);
index d83211b..96c1705 100644 (file)
 
 #cmakedefine LWS_FALLBACK_GETHOSTBYNAME
 
+#cmakedefine LWS_WITH_STATS
+
 /* OpenSSL various APIs */
 
 #cmakedefine LWS_HAVE_TLS_CLIENT_METHOD