Skip to content

Commit

Permalink
[WIP] feat(proxy-wasm) metrics
Browse files Browse the repository at this point in the history
  • Loading branch information
casimiro committed May 13, 2024
1 parent 1716a7e commit c164679
Show file tree
Hide file tree
Showing 36 changed files with 2,982 additions and 74 deletions.
9 changes: 7 additions & 2 deletions config
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ NGX_WASMX_INCS="\
$ngx_addon_dir/src/common \
$ngx_addon_dir/src/common/proxy_wasm \
$ngx_addon_dir/src/common/shm \
$ngx_addon_dir/src/common/metrics \
$ngx_addon_dir/src/common/lua"

NGX_WASMX_DEPS="\
Expand All @@ -141,7 +142,9 @@ NGX_WASMX_DEPS="\
$ngx_addon_dir/src/common/proxy_wasm/ngx_proxy_wasm_properties.h \
$ngx_addon_dir/src/common/shm/ngx_wasm_shm.h \
$ngx_addon_dir/src/common/shm/ngx_wasm_shm_kv.h \
$ngx_addon_dir/src/common/shm/ngx_wasm_shm_queue.h"
$ngx_addon_dir/src/common/shm/ngx_wasm_shm_queue.h \
$ngx_addon_dir/src/common/metrics/ngx_wa_histogram.h \
$ngx_addon_dir/src/common/metrics/ngx_wa_metrics.h"

NGX_WASMX_SRCS="\
$ngx_addon_dir/src/ngx_wasmx.c \
Expand All @@ -155,7 +158,9 @@ NGX_WASMX_SRCS="\
$ngx_addon_dir/src/common/proxy_wasm/ngx_proxy_wasm_util.c \
$ngx_addon_dir/src/common/shm/ngx_wasm_shm.c \
$ngx_addon_dir/src/common/shm/ngx_wasm_shm_kv.c \
$ngx_addon_dir/src/common/shm/ngx_wasm_shm_queue.c"
$ngx_addon_dir/src/common/shm/ngx_wasm_shm_queue.c \
$ngx_addon_dir/src/common/metrics/ngx_wa_histogram.c \
$ngx_addon_dir/src/common/metrics/ngx_wa_metrics.c"

# wasm

Expand Down
16 changes: 16 additions & 0 deletions docs/DIRECTIVES.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ By alphabetical order:
- [resolver_timeout](#resolver_timeout)
- [shm_kv](#shm_kv)
- [shm_queue](#shm_queue)
- [slab_size](#slab_size)
- [socket_buffer_size](#socket_buffer_size)
- [socket_buffer_reuse](#socket_buffer_reuse)
- [socket_connect_timeout](#socket_connect_timeout)
Expand Down Expand Up @@ -57,6 +58,8 @@ By context:
- [tls_trusted_certificate](#tls_trusted_certificate)
- [tls_verify_cert](#tls_verify_cert)
- [tls_verify_host](#tls_verify_host)
- `metrics{}`
- [slab_size](#slab_size)
- `wasmtime{}`
- [cache_config](#cache-config)
- [flag](#flag)
Expand Down Expand Up @@ -525,6 +528,19 @@ policy, and writes will fail when the allocated memory slab is full.

[Back to TOC](#directives)

shm_queue
---------

**usage** | `slab_size <size>;`
------------:|:----------------------------------------------------------------
**contexts** | `metrics{}`
**default** | `12m`
**example** | `slab_size 5m;`

Set the `size` of the shared memory slab dedicated to metrics storage.

[Back to TOC](#directives)

socket_buffer_reuse
-------------------

Expand Down
8 changes: 4 additions & 4 deletions docs/PROXY_WASM.md
Original file line number Diff line number Diff line change
Expand Up @@ -536,10 +536,10 @@ SDK ABI `0.2.1`) and their present status in ngx_wasm_module:
`proxy_enqueue_shared_queue` | :heavy_check_mark: | No automatic eviction mechanism if the queue is full.
`proxy_resolve_shared_queue` | :x: |
*Stats/metrics* | |
`proxy_define_metric` | :x: |
`proxy_get_metric` | :x: |
`proxy_record_metric` | :x: |
`proxy_increment_metric` | :x: |
`proxy_define_metric` | :heavy_check_mark: | Support for histograms NYI.
`proxy_get_metric` | :heavy_check_mark: |
`proxy_record_metric` | :heavy_check_mark: |
`proxy_increment_metric` | :heavy_check_mark: |
*Custom extension points* | |
`proxy_call_foreign_function` | :x: |

Expand Down
26 changes: 26 additions & 0 deletions src/common/debug/ngx_wasm_debug_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include <ngx_http_wasm.h>
#endif

#include <ngx_wa_metrics.h>

#if (!NGX_DEBUG)
# error ngx_wasm_debug_module included in a non-debug build
#endif
Expand All @@ -20,6 +22,11 @@
static ngx_int_t
ngx_wasm_debug_init(ngx_cycle_t *cycle)
{
size_t long_metric_name_len = NGX_MAX_ERROR_STR;
uint32_t mid;
ngx_str_t metric_name;
u_char buf[long_metric_name_len];

static ngx_wasm_phase_t ngx_wasm_debug_phases[] = {
{ ngx_string("a_phase"), 0, 0, 0 },
{ ngx_null_string, 0, 0, 0 }
Expand All @@ -41,6 +48,25 @@ ngx_wasm_debug_init(ngx_cycle_t *cycle)
ngx_wasm_phase_lookup(&ngx_wasm_debug_subsystem, 3) == NULL
);

metric_name.len = long_metric_name_len;
metric_name.data = buf;

/* invalid metric name length */
ngx_wa_assert(
ngx_wa_metrics_add(ngx_wasmx_metrics(),
&metric_name,
NGX_WA_METRIC_COUNTER,
&mid) == NGX_ERROR
);

/* invalid metric type */
ngx_wa_assert(
ngx_wa_metrics_add(ngx_wasmx_metrics(),
&metric_name,
100,
&mid) == NGX_ERROR
);

return NGX_OK;
}

Expand Down
225 changes: 225 additions & 0 deletions src/common/metrics/ngx_wa_histogram.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
#ifndef DDEBUG
#define DDEBUG 0
#endif
#include "ddebug.h"

#include <ngx_wasm.h>
#include <ngx_wa_histogram.h>

#define NGX_WA_MIN_BIN 5
#define NGX_WA_MAX_BIN 20
#define NGX_WA_BIN_INCREASE 5


static uint32_t
bin_log2_upper_bound(ngx_int_t n)
{
uint32_t upper_bound = 2;

if (n < 2) {
return 1;
}

for (n = n - 1; n >>= 1; upper_bound <<= 1) { /* void */ }

return upper_bound;
}


static ngx_int_t
histogram_grow(ngx_wa_metrics_t *metrics, ngx_wa_metrics_histogram_t *h,
ngx_wa_metrics_histogram_t **out)
{
size_t old_size, size;
ngx_int_t rc = NGX_OK;
ngx_uint_t n;
ngx_wa_metrics_histogram_t *new_h = NULL;

if (h->n_bins == NGX_WA_MAX_BIN) {
return NGX_ERROR;
}

ngx_log_debug(NGX_LOG_DEBUG_WASM, metrics->shm->log, 0,
"growing histogram");

n = ngx_min(NGX_WA_BIN_INCREASE, NGX_WA_MAX_BIN - h->n_bins);
old_size = sizeof(ngx_wa_metrics_histogram_t)
+ sizeof(ngx_wa_metrics_bin_t) * h->n_bins;
size = old_size + sizeof(ngx_wa_metrics_bin_t) * n;

if (metrics->shm->eviction == NGX_WASM_SHM_EVICTION_NONE) {
ngx_wasm_shm_lock(metrics->shm);
}

new_h = ngx_slab_calloc_locked(metrics->shm->shpool, size);
if (new_h == NULL) {
rc = NGX_ERROR;
goto error;
}

ngx_memcpy(new_h, h, old_size);
ngx_slab_free_locked(metrics->shm->shpool, h);

new_h->n_bins += n;
*out = new_h;

error:

if (metrics->shm->eviction == NGX_WASM_SHM_EVICTION_NONE) {
ngx_wasm_shm_unlock(metrics->shm);
}

return rc;
}


static ngx_wa_metrics_bin_t *
histogram_bin(ngx_wa_metrics_t *metrics, ngx_wa_metrics_histogram_t *h,
ngx_uint_t n, ngx_wa_metrics_histogram_t **out)
{
size_t i, j = 0;
uint32_t ub = bin_log2_upper_bound(n);
ngx_wa_metrics_bin_t *b;

for (i = 0; i < h->n_bins; i++) {
b = &h->bins[i];
j = (j == 0 && ub < b->upper_bound) ? i : j;

if (b->upper_bound == ub) {
return b;

} else if (b->upper_bound == 0) {
break;
}
}

if (i == h->n_bins) {
if (out && histogram_grow(metrics, h, out) == NGX_OK) {
h = *out;

} else {
ngx_wasm_log_error(NGX_LOG_WARN, metrics->shm->log, 0,
"cannot add a new histogram bin for value "
"\"%uD\", returning next closest bin", n);
return &h->bins[j];
}
}

/* shift bins to create space for the new one */
ngx_memcpy(&h->bins[j + 1], &h->bins[j],
sizeof(ngx_wa_metrics_bin_t) * (i - j));

h->bins[j].upper_bound = ub;
h->bins[j].count = 0;

return &h->bins[j];
}


void
ngx_wa_metrics_histogram_get(ngx_wa_metrics_t *metrics, ngx_wa_metric_t *m,
ngx_uint_t slots, ngx_wa_metrics_histogram_t *out)
{
size_t i, j = 0;
ngx_wa_metrics_bin_t *b, *out_b;
ngx_wa_metrics_histogram_t *h;

for (i = 0; i < slots; i++) {
h = m->slots[i].histogram;

for (j = 0; j < h->n_bins; j++) {
b = &h->bins[j];
if (b->upper_bound == 0) {
break;
}

out_b = histogram_bin(metrics, out, b->upper_bound, NULL);
out_b->count += b->count;
}
}
}

#if (NGX_DEBUG)
static void
histogram_log(ngx_wa_metrics_t *metrics, ngx_wa_metric_t *m, uint32_t mid)
{
size_t i, size = sizeof(ngx_wa_metrics_histogram_t)
+ sizeof(ngx_wa_metrics_bin_t)
* NGX_WA_MAX_BIN;
ngx_wa_metrics_bin_t *b;
ngx_wa_metrics_histogram_t *h;
u_char *p, buf[size], s_buf[NGX_MAX_ERROR_STR];

ngx_memzero(buf, size);

p = s_buf;
h = (ngx_wa_metrics_histogram_t *) buf;
h->n_bins = NGX_WA_MAX_BIN;
h->bins[0].upper_bound = NGX_MAX_UINT32_VALUE;

ngx_wa_metrics_histogram_get(metrics, m, metrics->workers, h);

for (i = 0; i < h->n_bins; i++) {
b = &h->bins[i];
if (b->upper_bound == 0) {
break;
}

p = ngx_sprintf(p, " %uD: %uD;", b->upper_bound, b->count);
}

ngx_log_debug3(NGX_LOG_DEBUG_WASM, metrics->shm->log, 0,
"histogram \"%uD\": %*s", mid, p - s_buf - 1, s_buf + 1);
}
#endif

ngx_int_t
ngx_wa_metrics_histogram_add_locked(ngx_wa_metrics_t *metrics,
ngx_wa_metric_t *m)
{
size_t i;
uint16_t n_bins = NGX_WA_MIN_BIN;
ngx_wa_metrics_histogram_t **h;

for (i = 0; i < metrics->workers; i++) {
h = &m->slots[i].histogram;
*h = ngx_slab_calloc_locked(metrics->shm->shpool,
sizeof(ngx_wa_metrics_histogram_t)
+ sizeof(ngx_wa_metrics_bin_t) * n_bins);
if (*h == NULL) {
goto error;
}

(*h)->n_bins = n_bins;
(*h)->bins[0].upper_bound = NGX_MAX_UINT32_VALUE;
}

return NGX_OK;

error:

for (/* void */ ; i > 0; i--) {
ngx_slab_free_locked(metrics->shm->shpool, m->slots[i - 1].histogram);
}

return NGX_ERROR;
}


ngx_int_t
ngx_wa_metrics_histogram_record(ngx_wa_metrics_t *metrics, ngx_wa_metric_t *m,
ngx_uint_t slot, uint32_t mid, ngx_uint_t n)
{
ngx_wa_metrics_bin_t *b;
ngx_wa_metrics_histogram_t *h;

h = m->slots[slot].histogram;
b = histogram_bin(metrics, h, n, &m->slots[slot].histogram);
b->count += 1;

#if (NGX_DEBUG)
histogram_log(metrics, m, mid);
#endif

return NGX_OK;
}
16 changes: 16 additions & 0 deletions src/common/metrics/ngx_wa_histogram.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#ifndef _NGX_WA_HISTOGRAM_H_INCLUDED_
#define _NGX_WA_HISTOGRAM_H_INCLUDED_


#include <ngx_wa_metrics.h>


ngx_int_t ngx_wa_metrics_histogram_add_locked(ngx_wa_metrics_t *metrics,
ngx_wa_metric_t *m);
ngx_int_t ngx_wa_metrics_histogram_record(ngx_wa_metrics_t *metrics,
ngx_wa_metric_t *m, ngx_uint_t slot, uint32_t mid, ngx_uint_t n);
void ngx_wa_metrics_histogram_get(ngx_wa_metrics_t *metrics, ngx_wa_metric_t *m,
ngx_uint_t slots, ngx_wa_metrics_histogram_t *out);


#endif /* _NGX_WA_HISTOGRAM_H_INCLUDED_ */
Loading

0 comments on commit c164679

Please sign in to comment.